【effective C++】05、了解C++默默编写并调用的函数

1、编译器会暗自的为类创建:

(1)默认的构造函数
(2)拷贝构造函数
(3)拷贝赋值操作赋
(4)构析函数例子:

Empty{}; 

声明上面的类就如同你写下了下面的代码:

Empty{ 
    publicEmpty(){/*~~~*/} 
        Emptyconst Empty& rhs){/*~~~*/} 
        〜Empty(){/*~~~*/} 
        Empty& operator =(const Empty&rhs){/*~~~*/} 
}; 

只有上面的函数需要被调用的时候才会被编译器创建出来:

Empty e1;       //调用默认构造函数
                //析构函数
Empty e2(e1;    //复制构造函数
e2 = e1;        //赋值操作赋重载函数

2、默认函数的分析

2.1、默认构造函数和分构函数

template<typeame T>
class NameObject{
    public:
        NameObject(const char* name, const T& value){/*~~~*/}
        NameObject(const std::string& name, const T& value){/*~~~*/}
        /*...*/
    private:
        std::string nameValue;
        T objectValue;
};

上面的例子,由于已经声明了有构造函数,那么编译器不再创建默认的构造函数。也就是说当你设计一个class并且构造函数要求有实参,就不必担心编译器会为你添加一个无实参的构造函数来覆盖掉你的版本。

2.2、copy构造函数

上面的例子NameObject既没有声明拷贝构造函数,也没有声明赋值操作符赋重载函数,所有编译器会为其创建函数,其中copy构造函数的用法:

NameObject<int> no1("Smallest Prime Number", 2);//调用自己设计的构造函数
NameObject <int> no2(no1); //调用编译器生成的拷贝构造函数

编译器生成的拷贝构造函数必须以no1的成员为初始值对no2的成员nameValue和objectValue进行设定。其中nameValue的类型是string,初始化的方式是调用string的拷贝构造函数并以no1.nameValue为实参;另一个成员objectValue的类型是int,int为内置类型,所以no2.objectValue会以拷贝no1.objectValue内的每一个bits来完成初始化。

2.3、copy assignment操作赋

copy assignment操作赋在很多情况下可以直接使用,但是在如下情况下要自己定义copy assignment 操作符,例如:

std::string newDog("Jack");
std::string oldDog("Hans");
NameObject<int> j(newDog, 2);
NameObject<int> h(oldDog,36);
p = s;

j和h分别调用自己定义的有实参的构造函数,但是,在执行p=s语句的时候:
1、编译器会拒绝编译这一行赋值操作,如果你想在内含reference成员的类内支持赋值运算操作,你必须自己定义copy assignment操作赋。
另外:
2、对于内含const成员的类,编译器也不知道如何修改const成
3、如果某个基类将copy assignmentt操作赋声明为private,编译器拒绝为其生成一个copy assignment操作符,因为派生创建的copy assignment操作赋无法调用基类的copy assignment操作赋,也就无法处理基类中的成员。

猜你喜欢

转载自blog.csdn.net/u013108511/article/details/80568943