3C++类

目录
1.空类
2.构造函数
3析构函数
4.拷贝构造
5.赋值构造
6.取地址函数重载
7.初始化列表
8.隐含的this指针

第一空类

空类是没有任何成员属性的类
空类对象在内存中仍然 占据至少 1 字节空间,以确保不同对象地址不同(否则两个对象地址可能一样,无法区分)。
C++类的计算大小和C语言的结构体是一样的,不需要计算C++类的成员方法。
下面两种叫法是一样的
C++类的变量和函数
C++类的成员属性和成员方法

C++类只需要存储成员属就行了,成员方法都是要一样的,只是处理不同对象的数据而已。

创建一个类就相当于自定义一个数据类型,首先是声明,然后是定义

第二构造函数

1.没有自定义构造函数

#include
using namespace std;

class date
{
public:
	date(int year = 2000,int month = 4,  int day = 10)
		:_year(year)
		,_month(month)
		,_day(day)
		// c++初始化列表才是成员属性定义的地方
	{
		cout<< " date " <<endl;
	}
	
	void print()
	{
		cout<< this->_year << " " << this->_month << " " << this->_day <<endl;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

class Time
{
public:
	// 这里有问题还需要研究一下!!!
	//Time(int hour = 1, int mintes = 1, int second = 1)
	//	:_hour(hour)
	//	,_mintes(mintes)
	//	,_second(second)
	
	Time()
	{
		cout<< " time " <<endl;
	}


private:
	int _hour;
	int _mintes;
	int _second;
};

class date2
{
public:
	void print()
	{
		cout<< this->_year << " " << this->_month << " " << this->_day <<endl;
	}
	
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
int main()
{
	// c++会自动调用我们已经写好的构造函数
	date d1; // 调用默认的缺省参数
	d1.print();
	date d2(11,22,33); // 这里面没有进行日期合法的检查!!!! 调用我们传入的参数
	d2.print();
	
	// 我们不写构造函数
	// 自定义类型编译器会调用它的默认构造函数
	date2 d3; // 这里会默认调用自定义类型的构造函数(应该自定义类型默认构造函数)
	
}

2.自定义构造函数

#include 
using namespace std;

class Time {
public:
    Time() 
    {
        _hour = 0;    
        _minute = 0;  
        _second = 0;
        cout << "Time constructor" << endl;
    }

    void print() const {
        cout << _hour << ":" << _minute << ":" << _second;
    }

private:
    int _hour;
    int _minute; 
    int _second;
};

class Date {  
public:
    Date(int year = 2000, int month = 1, int day = 1)
        : _year(year)
        , _month(month)
        , _day(day)
        , _t() 
    {  
        cout << "Date constructor" << endl;
    }

    void print() const
   {
        cout << _year << "-" << _month << "-" << _day << " ";
        _t.print();  
        cout << endl;
    }

private:
    int _year;
    int _month;
    int _day;
    Time _t;
};

int main() {
    Date d1;  // 调用 Date(),内部调用 Time()
    d1.print();

    Date d2(2023, 5, 15);  // 调用 Date(2023, 5, 15),内部调用 Time()
    d2.print();

    return 0;
}

第三析构函数

C++强调对自定义类型的数据进行初始化和清理工作。
析构函数,在生命周期结束的时候自动调用析构函数,清理类自己开辟的资源。解决了c语言容易忘记的缺点。

1.没有自定义构造函数

#include 
using namespace std;

class a
{
public:
	a(int x = 1, int y = 1, int z = 1)
		:_x(x)
		,_y(y)
		,_z(z)
	{
		cout<< " a的构造函数 " <<endl;
	}
	
	~a()
	{
		cout<< " ~a的析构函数 " <<endl;
	}

private:
	int _x;
	int _y;
	int _z;
};

class b
{
private:
	int _x;
	a _a;
};
int main()
{
	b _b;
}

2.自定义析构函数

#include 
using namespace std;

class a
{
public:
	a(int x = 1, int y = 1, int z = 1)
		:_x(x)
		,_y(y)
		,_z(z)
	{
		cout<< " a的构造函数 " <<endl;
	}
	
	~a()
	{
		cout<< " ~a的析构函数 " <<endl;
	}

private:
	int _x;
	int _y;
	int _z;
};

class b
{
public:
	b(int x)
		:_x(x)
		,_a(2,2,2)
	{
		cout<< " b的构造函数 " <<endl;
	}
	
	~b()
	{
		cout<< " b的析构函数 " <<endl;
	}
	
private:
	int _x;
	a _a;
};
int main()
{
	b _b;
}

第四拷贝构造

拷贝构造:这里就是用已经存在的对象,去构造一个一一模一样的对象出来。这里面存在深浅拷贝的问题,先来了解浅拷贝。

#include 
using namespace std;

class a
{
public:
	a(int x = 1, int y = 1, int z = 1)
		:_x(x)
		,_y(y)
		,_z(z)
	{
		cout<< " a的构造函数 " <<endl;
	}
	
	// 拷贝构造无返回值
	a(const a& that)
	{
		if(this != &that)
		{
			this->_x = that._x;
			this->_y = that._y;
			this->_z = that._z;
		}
	}
	
	void print()
	{
		cout<<  this->_x <<endl;
		cout<<  this->_y <<endl;
		cout<<  this->_z <<endl;
	}
		
	~a()
	{
		cout<< " ~a的析构函数 " <<endl;
	}

private:
	int _x;
	int _y;
	int _z;
};


int main()
{
	a a1;
	a1.print();
	a a2(a1);
	a2.print();
	
	a a3 = a1; // 注意这也是拷贝构造,实际上a2并不存在的
}

第五赋值构造

赋值构造:两个对象都是存在的,只不过是想把一个对象的值赋值给另一个对象而已!

#include 
using namespace std;

class a
{
public:
	a(int x = 1, int y = 1, int z = 1)
		:_x(x)
		,_y(y)
		,_z(z)
	{
		cout<< " a的构造函数 " <<endl;
	}
	
	// 拷贝构造无返回值
	a(const a& that)
	{
		if(this != &that)
		{
			this->_x = that._x;
			this->_y = that._y;
			this->_z = that._z;
		}
	}
	a& operator=(const a& that)
	{
		if(this != &that)
		{
			this->_x = that._x;
			this->_y = that._y;
			this->_z = that._z;
		}
		
		return *this; // 为了实现连续复制而已
	}
	
	void print()
	{
		cout<<  this->_x <<endl;
		cout<<  this->_y <<endl;
		cout<<  this->_z <<endl;
	}
		
	~a()
	{
		cout<< " ~a的析构函数 " <<endl;
	}

private:
	int _x;
	int _y;
	int _z;
};


int main()
{
	a a4(2,3,4);
	a a5(0,0,0);
	
	a4.print();
	a5.print();
	a4 = a5;
	a4.print();
	a5.print();

}

第六取地址函数重载

就是取到一个对象的地址,当然了,你自己实现 不让编译取到你的类的地址也行的!
这里的重载涉及到 const成员函数的

#include
class A 
{
public:
    A* operator&() 
    {
        cout << "重载了取地址符号" << endl;
        return this;
    }
    
     const A* operator&() const
    {
        cout << "重载了取地址符号" << endl;
        return this;
    }
};

int main() 
{
    A a1;
    const A a2;

    A* p1 = &a1;        // 调用 A* operator&()
    const A* p2 = &a2;  // 调用 const A* operator&() const
}

第七初始化列表

C++里面有三类成员变量,需要在初始化列表进行初始化
引用成员属性,const修饰的成员属性, 没有默认构造函数的自定义对象
初始化列表和定义的顺序最好 一样,否则会初始化不完全的!!!

#include 
using namespace std;

class A
{
public:
	A(int x, int y, int z)
		:_x(x)
		,_y(y)
		,_z(z)		
	{
		cout<< " A的初始化 " <<endl;
	}
private:
	int _x;
	int _y;
	int _z;
};

class B
{
public:
	B(int x = 10, int y = 1000)
		:_x(x)
		,_y(100)
		,_A(2,3,4)
		,_r(x)
	{
		cout<< " B的构造函数 " <<endl;
	}	
private:
	int _x;
	const int _y;
	A _A;
	int& _r;

};


int main() {
		B b;
    return 0;
}

第八隐含的this指针

类在访问自己的变量的时候,实际上已经隐士的传递 了this指针,通过this指针访问数据。同样我们的函数,通过this指针,能够让函数知道我们 处理的数据是哪个对象的。

精简版总结:
在 C++ 中,类的成员函数在调用时会隐式传入一个 this 指针,指向调用该函数的对象。
成员函数正是通过这个 this 指针来访问对象的成员变量,确保函数处理的是当前对象的数据。
虽然成员函数本身只在代码段中保存一份,但通过 this,它就能“知道”当前操作的是哪个对象,从而实现对象的行为。

#include 
using namespace std;

class A
{
public:
	A(int x, int y, int z)
		:_x(x)
		,_y(y)
		,_z(z)		
	{
		cout<< " A的初始化 " <<endl;
	}
	
	void print()
	{
		cout<< this->_x <<endl;
		cout<< this->_y <<endl;
		cout<< this->_z <<endl;
	}
	
private:
	int _x;
	int _y;
	int _z;
};



int main() {
		A a(1,2,3);
		a.print(); // a.print(&a),这里已经把的的地址传递了
    return 0;
}

你可能感兴趣的:(c++,c++,开发语言)