一、拷贝构造

当你使用一个实例对象去初始化另一个实例对象的时候,这两个实例对象使用的是同一个内存空间。

#include <iostream>
using namespace std;

class Player
{
private:
    int *i;

public:
    Player()
    {
        this->i = (int *)malloc(sizeof(int));
        *this->i = 10;
        cout << "constrcut" << endl;
    }
    ~Player()
    {
        if (!this->i)
            return;

        cout << "in destrcut address = " << this->i << endl;
        free(this->i);
    }
    void run()
    {
        cout << "run i = " << this->i << endl;
    }
};

int main(void)
{
    Player p1;
    Player p2 = p1;
    p1.run();
    p2.run();
}

如以上代码,构造函数会被调用一次,而析构函数会被对此调用。 p2是一个新的变量,是被p1对象进行直接赋值的。 这就意味着他们是共用同一内存空间。

那么问题来了,在不改变main方法中的代码的情况下,如何分配不同的内存空间给这两个对象?

答案就是拷贝构造

拷贝构造函数用于拷贝对象。也就是说,这个构造函数的参数是这个类的对象,执行这个构造函数之后,会产生一个与原来对象一样的对象(实际上是用原来对象的数据初始化了一个对象)。

二、静态成员

  • 如果类中有静态成员,则编译器会当作这是一个声明而已,表明在这个文件的某处,你必须定义它。
#include <iostream>

class A
{
private:
    static int i;

public:
    A(){};
    void print() { std::cout << i << std::endl; };
    void set(int ii) { i = ii; };
};

int A::i = 12; // 必须要定义,否则会报linker错误

int main(void)
{
    A a;
    a.print();
}
  • 初始化列表只能对非静态变量进行初始化。 warn
  • 静态成员方法可以直接通过这个类名加上方法名去访问。
  • 静态成员函数只能访问静态的成员变量(因为没有this)。
#include <iostream>

class A
{
private:
    static int i;

public:
    A(){};
    void print() { std::cout << i << std::endl; };
    void set(int ii) { i = ii; };
    static void say(int ii) { std::cout << ii << this->i << std::endl; }; // this只能用于非静态成员函数内部。
};
int A::i = 12;
int main(void)
{
    A a;
    a.print();
    A::say(0);
}

三、模板

#include <iostream>

template <typename T>
void print(T value)
{
    std::cout << value << std::endl;
};
int main(void)
{
    print(1);
    print(2.3);
    print("hello");
}

C++中的模板就相当于TS中的泛型