易忘知识点:
- 编译器产生出的析构函数不是虚析构函数,除非这个类的基类自身声明了虚析构函数。
- 如果某个基类将赋值操作符声明为private,编译器将拒绝为其派生类生成赋值操作符。因为编译器想象调用基类的赋值操作符。
结论1:编译器生成的拷贝构造函数,对类成员调用类成员的拷贝构造函数来创建类成员并初始化,对内置类型成员拷贝每一个bits来创建内置成员并初始化。
代码段1:NameObject.h文件
#ifndef NAMEOBJECT_H #define NAMEOBJECT_H #include <string> template <typename T> class CNameObject { public: CNameObject(const std::string& name, const T& object):m_NameValue(name), m_ObjectValue(object){} /*这部分代码等价于编译器生成的拷贝构造函数的功能 CNameObject (CNameObject& rhs):m_NameValue(rhs.GetNameValue()),m_ObjectValue(rhs.GetObjectValue()){} std::string& GetNameValue() {return m_NameValue;} T& GetObjectValue() {return m_ObjectValue;}*/ private: std::string m_NameValue; T m_ObjectValue; };
结论2:编译器生成赋值操作符的条件是,生成得到的代码是合法的,例如类成员中有一个引用成员和一个const成员,我们已知引用变量和const变量均不能赋值,因此如果编译器为这两个变量定义赋值动作会使得编译器不知如何是好,这时编译器放弃为该类创建赋值操作符(无论此时所有成员均是引用变量和const变量,还是只有部分成员是引用变量和const变量)。此时如果你仍想让该类型支持赋值操作符,则必须自己定义。
代码段2.1:NameObject2.h文件
#ifndef NAMEOBJECT2_H #define NAMEOBJECT2_H #include <string> template <typename T> class CNameObject2 { public: CNameObject2(std::string& name, const T& object/*, int a*/):m_NameValue(name), m_ObjectValue(object)/*, m_Spec(a)*/{} private: std::string& m_NameValue; const T m_ObjectValue; /*int m_Spec;*/ }; #endif
代码段2.2:main.cpp文件
#include "NameObject.h" #include "NameObject2.h" #include <string> int main() { std::string s1 = "abc"; std::string s2 = "def"; CNameObject2<int> n1(s1,5/*,3*/); CNameObject2<int> n2(s2,4/*,2*/); n2 = n1; //error return 0; }
时间: 2024-12-28 02:17:27