c语言先声明后初始化(C理解初始化操作)

对于普通变量来说,其初始化和赋值的理解较为简单,只是=操作符在不同的上下文中即可用于初始化,也可用于赋值的更新操作:

int a = 5; // 声明、定义变量的同时初始化 int b(6); // 声明、定义变量的同时初始化 a = 6; // 赋值操作,用于变量的更新 b = 7; // 赋值操作,用于变量的更新 const int c = 8; // 因为是只读,此后不能再更新,自然需要在声明、定义的同时初始化 // const在C中是只读变量,C 视上下文可以实现为只读变量或常量 int arr[5]; // 虽然arr有常量性质,但其元素却是可写的变量 int &r = a; // 引用可以理解为一个实现了自动解引用的有常量性质的指针

C 的类除了封装、继承、多态等特性,还可以通过构造函数来自动初始化数据成员,也可以通过拷贝构造函数通过另一个同类的对象来初始化自己。

C 通过重载来实现拷贝构造和重载=操作符,其关键在于理解初始化操作和赋值操作的区别:

初始化:被初始化的对象正在创建。

赋值:被赋值的对象已经存在。

对于C 的类和对象构造,一些特殊成员需要在创建的同时做初始化,其构造函数的函数体只是赋值的更新操作,为此,C 提供了一种初始化列表的构造机制。

1 定义对象变量并初始化

在拷贝构造函数中,可以用另一个同类对象来初始化自己:

#include <iostream> using namespace std; class AA { public: AA() //无参构造函数默认构造函数 { cout<<"我是构造函数,自动被调用了"<<endl; } AA(int _a) //有参构造函数 { a = _a; } AA(const AA &obj2) { cout<<"我也是构造函数,我是通过另外一个对象obj2,来初始化我自己"<<endl; a = obj2.a 10; } ~AA() { cout<<"我是析构函数,自动被调用了"<<endl; } void getA() { printf("a:%d \n", a); } protected: private: int a; }; void ObjPlay01() { AA a1; // 变量定义 //用对象1 初始化对象a2、a3,所谓初始化,发生在对象构造的相同时间 AA a2 = a1; //定义对象变量并初始化 AA a3(a1); a2 = a1; // 用a1来=号给a2 编译器给我们提供的浅copy,发生在对象构造以后 // } int main() { ObjPlay01(); while(1); return 0; }

2 类的对象做函数参数时,实参与形参的结合以及函数返回会调用拷贝构造函数

#include <iostream> using namespace std; class Location { public: Location( int xx = 0 , int yy = 0 ) { X = xx ; Y = yy ; cout << "Constructor Object.\n" ; } Location( const Location & p ) //拷贝构造函数 { X = p.X ; Y = p.Y ; cout << "Copy_constructor called." << endl ; } ~Location() { cout << X << "," << Y << " Object destroyed." << endl ; } int GetX () { return X ; } int GetY () { return Y ; } private : int X , Y ; } ; void f ( Location p ) { cout << "Funtion:" << p.GetX() << "," << p.GetY() << endl ; } void mainobjplay() { Location A ( 1, 2 ) ; //形参是一个元素,函数调用,会执行实参变量初始化形参变量 f ( A ) ; //实参与形参的结合会调用拷贝构造函数 } Location g() { Location A(1, 2); return A; //函数返回一个对象会调用拷贝构造函数 } void main() { mainobjplay(); g(); system("pause"); }

3 重载赋值运算符

重载的赋值运算符可以用同类的另一个对象来更新自己。

#include <iostream> using namespace std; class Name { public: Name(const char *pname) { size = strlen(pname); pName = (char *)malloc(size 1); strcpy(pName, pname); } Name(Name &obj) //用obj来初始化自己 { pName = (char *)malloc(obj.size 1); strcpy(pName, obj.pName); size = obj.size; } ~Name() { cout<<"开始析构"<<endl; if (pName!=NULL) { free(pName); pName = NULL; size = 0; } } void operator=(Name &obj3) // 重载赋值运算符 { if (pName != NULL) { free(pName); pName = NULL; size = 0; } cout<<"测试有没有调用我……"<<endl; //用obj3来=自己 pName = (char *)malloc(obj3.size 1); strcpy(pName, obj3.pName); size = obj3.size; } protected: private: char *pName; int size; }; void playObj() { Name obj1("obj1……"); Name obj2 = obj1; //obj2创建并初始化 Name obj3("obj3……"); //重载=号操作符 obj2 = obj3; //=号操作 cout<<"业务操作……5000"<<endl; } void main() { playObj(); system("pause"); }

4 对象初始化列表

类对象的构造顺序是这样的:

I 分配内存,调用构造函数时,隐式/显示的初始化各数据成员;

II 进入构造函数后在构造函数中执行一般赋值与计算。

在构造对象这种数据类型时,一些数据需要在构造的同时进行初始化,C 编译器使用初始化列表这种机制:

Constructor::Contructor() : m1(v1), m2(v1,v2), m3(v3) { // some other assignment operation }

情况一、数据成员是对象的情况;

如果在类的数据成员中有一个其它类的对象成员,而且这个成员它只有一个带参数的构造函数,没有默认构造函数。这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步,就会报错。

情况二、在继承情况下,通过显式调用父类的带参构造函数对父类数据成员进行初始化;

情况三、需要初始化const修饰的类成员

当类成员中含有一个const对象时,也必须要通过成员初始化列表进行初始化,因为这种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。

情况四、需要初始化引用成员数据;

当类成员中含有一个引用时,因为引用是一个有常量性质的特殊指针。

以上种情况以外的其它数据成员,也可以在初始化列表中进行初始化,以获得更高的效率。

成员变量的初始化顺序与声明的顺序相关,与在初始化列表中的顺序无关。

对于构造函数,按以下顺序调用:基类构造函数,派生类对象成员构造函数,派生类本身的构造函数。

初始化列表先于构造函数的函数体执行。

#include <iostream> using namespace std; #include <iostream> using namespace std; class Base { int n; public: Base(int m):n(m){ cout<<"Base is called\n";} ~Base(){} }; class Other { int m; public: Other(int a):m(a){ cout<<"Other is called\n";} }; class Derive:public Base { int v; const int cst; int &r; Other obj; public: Derive(int a,int b,int c):Base(a),obj(b),cst(c),r(a) { v = a; cout<<"Self is called\n"; } ~Derive(){} }; int main() { Derive dd(3,4,5); while(1); return 0; } /* Base is called Other is called Self is called */

c语言先声明后初始化(C理解初始化操作)(1)

-End-

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页