一.对象的构造(上)

Q:对象中成员变量的初始值是多少?

#include <iostream>

using namespace std;

class Test
{
	private:
		int i;
		int j;
	public:
		int getI()
		{
			return i;
		}
		int getJ()
		{
			return j;
		}
};

int main()
{
	Test t1;
	
	cout<<"t1.getI()="<<t1.getI()<<endl;
	cout<<"t1.getJ()="<<t1.getJ()<<endl;
}

输出的结果为

#include <iostream>

using namespace std;

class Test
{
	private:
		int i;
		int j;
	public:
		int getI()
		{
			return i;
		}
		int getJ()
		{
			return j;
		}
};


Test gt;

int main()
{
    cout<<"gt.getI()="<<gt.getI()<<endl;
    cout<<"gt.getJ()="<<gt.getJ()<<endl;
    
    Test t1;
    
    cout<<"t1.getI()="<<t1.getI()<<endl;
    cout<<"t1.getJ()="<<t1.getJ()<<endl;
    
    Test* pt = new Test;
    
    cout<<"pt->getI()="<<pt->getI()<<endl;
    cout<<"pt->getJ()="<<pt->getJ()<<endl;
    
    delete pt;
    
    return 0;
    
}

结果如图 小结 从程序设计的角度,对象只是变量 1.在栈上创建对象时,成员变量初始为随机值 2.在堆上创建对象时,成员变量初始值为随机值 3.在静态区创建对象时,成员变量初始值为0值

解决方案: 1.在类中提供一个public的intialize函数 2.对象创建后立即调用intialize函数进行初始化 示例

#include <iostream>

using namespace std;

class Test
{
	private:
		int i;
		int j;
	public:
		int getI()
		{
			return i;
		}
		int getJ()
		{
			return j;
		}
		void initialize()
        {
            i = 1;
            j = 2;
        } 
};


Test gt;

int main()
{
    gt.initialize();
    cout<<"gt.getI()="<<gt.getI()<<endl;
    cout<<"gt.getJ()="<<gt.getJ()<<endl;
    
    Test t1;
    //t1.initialize();
    cout<<"t1.getI()="<<t1.getI()<<endl;
    cout<<"t1.getJ()="<<t1.getJ()<<endl;
    t1.initialize();
    
    Test* pt = new Test;
    pt->initialize();
    cout<<"pt->getI()="<<pt->getI()<<endl;
    cout<<"pt->getJ()="<<pt->getJ()<<endl;
    
    delete pt;
    
    return 0;
    
}

运行结果 Q:当intialize的位置出现了改变的话,还会对其进行初始化吗 输出结果如图所示,发现intialize位置改变了之后,初始化也出现了问题 存在的问题 1.intialize只是一个普通函数,必须显示调用 2.如果为调用intialize函数,运行结果是不确定的 解决方法 C++中可以定义与类名相同的特殊成员函数--这种特殊的成员函数叫做构造函数 1.构造函数没有任何返回类型的声明 2.构造函数在对象定义时自动被调用

示例

#include <iostream>

using namespace std;

class Test
{
	private:
		int i;
		int j;
	public:
		int getI()
		{
			return i;
		}
		int getJ()
		{
			return j;
		}
        Test()
        {
            printf("Test() Begin\n");
        
            i = 1;
            j = 2;
        
            printf("Test() End\n");
        }
};


Test gt;

int main()
{

    cout<<"gt.getI()="<<gt.getI()<<endl;
    cout<<"gt.getJ()="<<gt.getJ()<<endl;
    
    Test t1;

    cout<<"t1.getI()="<<t1.getI()<<endl;
    cout<<"t1.getJ()="<<t1.getJ()<<endl;
    t1.initialize();
    
    Test* pt = new Test;

    cout<<"pt->getI()="<<pt->getI()<<endl;
    cout<<"pt->getJ()="<<pt->getJ()<<endl;
    
    delete pt;
    
    return 0;
    
}

运行结果 小结 1.每个对象在使用之前都应该初始化 2.类的构造函数用于对象的初始化 3.构造函数与类同名并且没有返回值 4.构造函数在对象定义时自动被调用

二.对象的构造(中)

带有参数的构造函数 1.构造函数可以根据需要定义参数 2.一个类中可以存在多个重载的构造函数 3.构造函数的重载遵循C++重载的规则 对象定义和对象声明不同 1.对象定义--申请对象的空间并调用构造函数 2.对象声明--告诉编译器存在这样一个对象 示例

#include <iostream>
using namespace std;

class Test
{
public:
    Test() 
    { 
        cout<<"Test()"<<endl;;
    }
    Test(int v) 
    { 
        cout<<"Test(int v)="<<v<<endl;
    }
};

int main()
{
    Test t;      // 调用 Test()
    Test t1(1);  // 调用 Test(int v)
    Test t2 = 2; // 调用 Test(int v)
    
    int i(100);
    
    cout<<"i="<<i<<endl;
    
    return 0;
}

结果 小结 1.构造函数可以根据需要定义参数 2.构造函数之间可以存在重载关系 3.构造函数遵循C++中重载函数的规则 4.对象定义时会触发构造函数的调用 5.在一些情况下可以手动调用构造函数

三.特殊的构造函数

1.无参构造函数--没有参数的构造函数,当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空 2.拷贝构造函数--参数为const class_name&的构造函数,当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值的复制

拷贝构造函数的意义 1.兼容C语言的初始化方式 2.初始化行为能够符合预期的逻辑 3.浅拷贝--拷贝后的物理状态相同 4.深拷贝--拷贝后的逻辑状态相同 小结 1.C++编译器会默认提供构造函数 2.无参构造函数用于定义对象的默认初始状态‘ 3.拷贝构造函数在创建对象时拷贝对象的状态 4.对象的拷贝由浅拷贝和深拷贝两种方式