本节知识点:
1.c++中的构造函数:
a.c++中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数。构造函数在定义的时候可以有参数,但是没有任何返回类型的声明。 b.在c++编译器中,在类定义对象的时候就会顺便自动调用这个对象的构造函数,有时候也需要手动调用,代码如下:#include注意:上面定义类的三种方式class list { private: int a; int b; int c; public: list(int v) { a = b = c = v; } void list_printf() { printf("%d %d %d \n",a,b,c); } }; int main() { list l(5); //自动调用方式一 list d = 6; //自动调用方式二 list p = list(7); //手动调用 l.list_printf(); d.list_printf(); p.list_printf(); list ar[3] = {1,2,3}; //对于类数组 只能这样手动调用了 list ar1[3] = {(1),(2),(3)}; list ar2[3] = {list(1),list(2),list(3)}; return 0; }
c.类的成员函数和普通函数一样都可以进行重载,也就是说构造函数支持重载,代码如下:
#included.两个特殊的构造函数:class list { private: int a; int b; int c; public: list() { a = 1; b = 2; c = 3; printf("list\n"); } list(int v) { a = b = c = v; } void list_printf() { printf("%d %d %d \n",a,b,c); } }; int main() { list a = list(); //无参数的构造函数的调用 list a1; //与上面语句等效 切记list a1(); 是错误的~~~ list l(5); //自动调用方式一 list d = 6; //自动调用方式二 list p = list(7); //手动调用 l.list_printf(); d.list_printf(); p.list_printf(); list ar[3] = {1,2,3}; //对于类数组 只能这样手动调用了 list ar1[3] = {(1),(2),(3)}; list ar2[3] = {list(1),list(2),list(3)}; return 0; }
无参构造函数:当类中没有定义构造函数时,编译器会默认提供一个无参构造函数,并且其函数体为空。其目的主要是为了,兼容那些没有定义构造函数的类的定义(因为我们知道定义类的时候,编译器会自动调用构造函数的),没有太多的实用价值。但是注意:第一可以自己定义无参构造函数,来代替编译器提供的那个函数,此时函数体就不再是空函数了。第二,没有构造函数的类的定义方式list a; 或者 list a = list(); 切记list a(); 是错误的方式!!! 拷贝构造函数:拷贝构造函数其实是一个参数为自己类的引用的构造函数,如:list(const list& l); 当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值的复制(默认的这个函数的功能是 list a = b; 把b类中的成员变量的值复制给a类中的成员变量,注意a b必须是同一个类)。但是你也可以自己定义拷贝构造函数,此时的函数功能就由你自己定了!!! 示例代码:
注意:1.当类中没有定义任何一个构造函数,c++编译器会提供无参构造函数和拷贝构造函数 2.当类中定义了任意的非拷贝构造函数时,c++编译器就不会提供无参构造函数 3.这里说下无参构造函数、有参构造函数、拷贝构造函数,他们的关系是重载的关系,在定义一个类的时候只能自动调用他们三者中的一个构造函数,选择方 式是根据定义方式来说的。#includeclass list { private: int a; int b; int c; public: list() { a = 1; b = 2; c = 3; printf("list\n"); } list(int z) { a = b = c = z; } void list_printf() { printf("%d %d %d \n",a,b,c); } list(const list& r) //可以屏蔽这个函数 看默认拷贝构造函数的功能 { printf("copy hello\n"); } }; int main() { list a = list(); //无参数的构造函数的调用 list a1; //与上面语句等效 切记list a1(); 是错误的~~~ list p(6); list q = p; q.list_printf(); return 0; }
2.c++类中的初始化列表:
a. 在类中的成员变量定义的时候,有些成员变量是需要赋初值的。比如说: const属性的只读变量、 引用、 只有有参构造函数的类。当存在这些不赋初值就报错的情况,而且类中的成员变量不能直接赋初值的时候,就需要用到初始化列表了。 b.初始化列表是写在构造函数后面,执行在构造函数前面,对类的成员变量进行初始化的语句,代码如下:#include针对上面的代码要注意几点: 第一:初始化列表是写在各个构造函数的后面的,切记成员变量一个都不能少否则编译出错,初始化列表是在构造函数执行之前执行的,成员变量的初始化顺序与在类中声明的顺序有关,与在初始化列表中的顺序无关。 第二:这个问题很重要,是关于c++中类的对象的赋值的问题,对于一个已经初始化完成的类的对象Test t1; 可以进行t1 = 10;的操作,此时调用t1的Test(int a)构造函数,但是要注意的是,如果有初始化列表,虽然t1的成员变量的值发生了变化,但是这个过程不再是初始化了,而是直接对t1的成员变量根据初始化列表中的值进行赋值操作。可以用conclass M { private: int mI; public: M(int i) { printf("M(int i), i = %d\n", i); mI = i; } int getI() { return mI; } }; class Test { private: const int c; M m1; M m2; public: Test() : c(1), m2(3), m1(2) //初始化列表中成员变量一个都不能少 { printf("Test()\n"); } Test(int z) : c(10), m2(30), m1(20) { printf("Test int\n"); } void print() { printf("c = %d, m1.mI = %d, m2.mI = %d\n", c, m1.getI(), m2.getI()); } }; int main() { Test t1(2); t1.print(); getchar(); return 0; }