From 43e6bf5ebae9599448585bc42d397d531e5a5b2f Mon Sep 17 00:00:00 2001 From: lion187 Date: Wed, 19 Jun 2019 15:34:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=BB=BA=E6=96=87=E4=BB=B6=20Software?= =?UTF-8?q?/Program/Language/Cpp/Cpp=5F=E9=BB=98=E8=AE=A4=E6=9E=84?= =?UTF-8?q?=E9=80=A0=E6=96=B9=E6=B3=95.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Program/Language/Cpp/Cpp_默认构造方法.md | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Software/Program/Language/Cpp/Cpp_默认构造方法.md diff --git a/Software/Program/Language/Cpp/Cpp_默认构造方法.md b/Software/Program/Language/Cpp/Cpp_默认构造方法.md new file mode 100644 index 0000000..7ee8701 --- /dev/null +++ b/Software/Program/Language/Cpp/Cpp_默认构造方法.md @@ -0,0 +1,83 @@ +# Cpp 默认构造方法 + +C++ 类可以有一个默认构造函数。在默认构造函数被需要的情况下,如果没有显式声明,则编译器自动为该类合成一个默认构造函数。当类只含有内置类型或复合类型的成员时,编译器是不会为类合成默认构造函数的。 + +合成默认构造函数总是不会初始化类的内置类型(int 等)及复合类型(数组、结构体等)的数据成员。 +分清楚默认构造函数被程序需要与被编译器需要,只有被编译器需要的默认构造函数,编译器才会合成它。 + +*注:C++另一种类型为 类类型* + +以下四种情况编译器需要默认构造函数: + +1. 含有类对象数据成员,该类对象类型有默认构造函数 + + 如果一个类没有任何构造函数,但是它含有一个类对象数据成员,且该类对象类型有默认构造函数,那么编译器就会为该类合成一个默认构造函数,不过这个合成操作只有在构造函数真正需要被调用的时候才会发生。 + +2. 基类带有默认构造函数的派生类 + + 当一个类派生自一个含有默认构造函数的基类时,该类也符合编译器需要合成默认构造函数的条件。编译器合成的默认构造函数将根据基类声明顺序调用上层的基类默认构造函数。同样的道理,如果设计者定义了多个构造函数,编译器将不会重新定义一个合成默认构造函数,而是把合成默认构造函数的内容插入到每一个构造函数中去。 + +3. 带有虚函数的类 + + 类带有虚函数可以分为两种情况:类本身定义了自己的虚函数 或 类从继承体系中继承了虚函数(成员函数一旦被声明为虚函数,继承不会改变虚函数的”虚性质“)。这两种情况都使一个类成为带有虚函数的类。这样的类也满足编译器需要合成默认构造函数的类,原因是含有虚函数的类对象都含有一个虚表指针vptr,编译器需要对vptr设置初值以满足虚函数机制的正确运行,编译器会把这个设置初值的操作放在默认构造函数中。如果设计者没有定义任何一个默认构造函数,则编译器会合成一个默认构造函数完成上述操作,否则,编译器将在每一个构造函数中插入代码来完成相同的事情。 + +4. 带有虚基类的类 + + 虚基类的概念是存在于类与类之间的,是一种相对的概念。例如类A虚继承于类X,则对于A来说,类X是类A的虚基类,而不能说类X就是一个虚基类。虚基类是为了解决多重继承下确保子类对象中每个父类只含有一个副本的问题。 + 一个参考代码如下,函数function参数pa的真正类型是可以改变的,既可以把A对象指针赋值给pa,也可以把对象指针赋值给pa,在编译阶段并无法确定pa存储的i是属于A还是C的虚基类对象。为了解决这问题,编译器将产生一个指向虚基类X的指针,使得程序得以在运行期确定经由pa而存取的X::i的实际存储位置。这个指针的安插,编译器将会在合成默认构造函数中完成,同样的,如果设计者已经写了多个构造函数,那么编译器不会重新写默认构造函数,而是把虚基类指针的安插代码插入已有的构造函数中。 + +```cpp +class X { public: int i; }; +class A : public virtual X{ public:int j; }; +class B : public virtual X{ public:double d; }; +class C : public A, public B{ public: int k; }; + +void function(A *pa) +{ + pa->i = 1000; +} +int main() +{ + A *a= new A(); + C *c= new C(); + function(a); //关注重点在这里 + function(c); //关注重点在这里 + return 0; +} +``` + +默认构造函数有两种情况: + + 没有带明显形参的构造函数,即是 A() 的形式 + 为全部形参提供了默认实参的构造函数,即是 A(int a=0,int b=0) 的形式 + +你好 + +```cpp +class A +{ +public: + A(int a=-1, bool b=true) { Va=a; Vb=b; } // 默认构造函数 + + int Va; bool Vb; +} + +int main() +{ + A a; // 调用类A的默认构造函数 +} +``` + +C++11中,当类中含有不能默认初始化的成员变量时,可以禁止默认构造函数的生成: + +```cpp +myClass()=delete; //表示删除默认构造函数 +myClass()=default; //表示默认存在构造函数 +``` + +当类中含有不能默认拷贝成员变量时,可以禁止默认构造函数的生成, + +```cpp +myClass(const myClass&)=delete; //表示删除默认拷贝构造函数,即不能进行默认拷贝 +myClass & operatir=(const myClass&)=delete; //表示删除默认拷贝构造函数,即不能进行默认拷贝 +```