/**
*一个类是另外一个类的成员属性,构造函数和析构函数的执行顺序。
* 1。构造函数,先执行其他类的构造,再执行本类构造。
* 2。析构函数和构造函数的执行顺序正好相反。
*/
class Phone {
public :
string p_Name;
Phone() {
cout << "Phone 默认构造函数执行。" << endl;
}
Phone(string pName) : p_Name(pName) {
cout << "Phone 有参构造函数执行。" << endl;
}
~Phone() {
cout << "Phone 析构函数执行。" << endl;
}
};
class Person113 {
public:
string m_Name;
Phone p_Name;
//再这里有一个隐示转化,Phone p_Name = pName; 这里就是通过隐示调用构造其他类有参构造函数进行。
//也就是上面的 Phone(string pName) : p_Name(pName) 构造函数。
Person113(string name, string pName) : m_Name(name), p_Name(pName) {
cout << "Person 构造函数执行。" << endl;
}
~Person113() {
cout << "Person 析构函数执行。" << endl;
}
};
void test() {
Person113 p("张三", "苹果");
}
int main() {
test();
return 0;
}
/**
* 静态成员函数:
* 1.所有的对象都共享一个函数。
* 2.静态成员函数,只能访问静态成员变量。
*
*/
class Person114 {
public:
//静态函数
static void func() {
m_Age = 10;
// m_Num = 20;//不允许访问非静态变量。
cout << "静态函数被调用" << endl;
}
//普通函数
void func2() {
cout << "静态函数被调用" << endl;
}
static int m_Age ;
int m_Num;
};
void test() {
Person114 p;
p.func(); //这是通过对象的方式调用。
Person114::func();//通过类名来访问。
}
int main() {
test();
return 0;
}
/**
*c++中对象模型和指针:
*1.c++编译器会给每一个空对象,分配一个字节的空间
*2.只有成员变量的数据会保存在对象上,其他的都不会保存在对象上。
*/
class Person115{
int m_A;//非静态成员变量。属于对象上。
static int m_B;//静态成员函数,不属于对象上。
void func(){//非静态成员函数,不属于对象上。
}
static void func2(){//静态成员函数,不属于对象上。
}
};
int Person115::m_B=0;
void test(){
Person115 p;
cout << sizeof (p)<<endl;//这里输出是1,c++编译器默认分配空对象是1。如果对象中没有任何数据。
}
void test01(){
Person115 p;
cout << sizeof (p)<<endl;//这里输出是4,因为有一个int 的4个字节。
}
int main(){
test01();
return 0;
}
/**
- this 指针:指向被调用成员函数所属的对象。
- 大白话,就是谁调用它,它就指向哪个对象。如果想返回对象本身,就return *this; 对this 进行解引用。
- c++ 是允许空指针调用成员函数。 只要里面没有引用this 就不会报错。 如果对this 做了判空处理,也可以调用。见例子test03()
*/
```cpp
class Person115{
public :
int age;
Person115(int age){
this->age = age;//this 指向的是谁调用它就是指向谁。
}
void addAge(const Person115 &person115){
this->age += person115.age; //这个函数,不能进行累加。链式编程
}
//链式累加。返回对象本身,这里注意,不能返回Person115值,那么这里就会调用copy 构造函数,每次生成一个新的Person115对象。
Person115 &linkAddAge(const Person115 &person115){
this->age += person115.age;
return *this;
}
void showClassName(){
cout << "Person115 class"<<endl;
}
void showClassAge(){
cout << "Person115 showClassAge:"<<this->age<<endl;
}
};
void test(){
Person115 person115(18);
cout << person115.age<<endl;
}
void test01(){
Person115 person115(10);
person115.addAge(person115);
cout << person115.age<<endl;
}
void test02(){
Person115 person115(10);
person115.linkAddAge(person115).linkAddAge(person115).linkAddAge(person115);
cout << person115.age<<endl;
}
void test03(){
Person115 * person115 = NULL;
person115->showClassName();//空指针是可以调用这个函数。
person115->showClassAge(); //这里会报错。因为调用age的时候,需要通过this->调用,this=NUll。
}
int main(){
// test();
// test01();
// test02();
test03();
return 0;
}
/**
* const 修饰成员函数:成为常函数。如果想修改这个对象属性,那么加入mutable
* const 修饰对象,叫做常对象,常对象只能调用常函数。
*/
class Person118 {
public:
Person118() {
}
void showAge() const { //这个就相当于const Person118 * const this; 常量指针常量。都不允许修改。
//在函数后面加入const 修饰的是this 指针。让this指向的值不修改。
//this->m_Age = 100;
this->m_B = 100;//加入了mutable 之后,即是在常函数中,也可以修改。
// this = NULL;//this 也是一个指针常量。this 是不允许被修改的。但是this 指向的值是可以修改的。
//上面这句话的理解为:Person118 * const this;是一个指针常量。
}
void func() {
}
int m_Age;
mutable int m_B;
};
void test() {
const Person118 p;
//常对象。也不允许修改这个对象的值。常对象只能调用常函数。
// 如果调用普通函数,那么有可能在普通函数中修改其对应的属性值。
p.m_B = 100;
// p.m_Age = 100;//这里不允许被修改。
p.showAge(); //ok,没有问题。常对象调用常函数。
// p.func();//不允许调用普通函数。如果在func里面修改值是不允许的。
}
int main() {
test();
return 0;
}
/**
* 友元:friend 就是声明一些特殊的函数活着类,来访问另一个类的私有成员。
* 友元的三种实现:
* 1.全局函数做友元。
* 2.类做友元。
* 3.成员函数做友元。
*/
//1.全局函数做友元。
class Building{
//这里是关键,让全局函数作为友元函数。这样其他的类就可以访问Building里面的私有成员。
friend void goodGay(Building &building);
public:
Building(){
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
public:
string m_SittingRoom;
private:
string m_BedRoom;
};
void goodGay(Building &building){
cout<<"访问的是:"<< building.m_SittingRoom<<endl;
cout<<"访问的是:"<< building.m_BedRoom<<endl;//理论上是不能访问Building的私有成员。这里作为友元函数可以访问。
}
void test(){
Building building;
goodGay(building);
}
int main(){
test();
return 0;
}
/**
* 友元:friend 就是声明一些特殊的函数活着类,来访问另一个类的私有成员。
* 友元的三种实现:
* 1.全局函数做友元。
* 2.类做友元。
* 3.成员函数做友元。
*/
//2.类做友元
class Building{
//这句话的意思是,让GoodGay类能访问Building 类的私有成员。
friend class GoodGay;
public :
Building();
string m_SittingRoom;
private :
string m_BedRoom;
};
class GoodGay{
public:
GoodGay();
Building *building;
void visit();
GoodGay(const GoodGay &goodGay){
building = goodGay.building;
}
~GoodGay(){
if(building != NULL){
delete building;
building = NULL;
}
}
};
//在类外进行构造函数初始化
Building::Building() {
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
//在类外进行构造函数初始化
GoodGay::GoodGay() {
building = new Building();
}
void GoodGay::visit() {
cout<<"GoodGay访问"<<building->m_SittingRoom<<endl;
cout<<"GoodGay访问"<<building->m_BedRoom<<endl;
}
void test(){
GoodGay goodGay;
goodGay.visit();
}
int main(){
test();
return 0;
}
//3.成员函数做友元。
class Building{
//这句话的意思是,GoodGay::visit成员方法能访问Building 类的私有成员。
friend void GoodGay::visit();
public :
Building();
string m_SittingRoom;
private :
string m_BedRoom;
};
class GoodGay{
public:
GoodGay();
Building *building;
void visit();
GoodGay(const GoodGay &goodGay){
building = goodGay.building;
}
~GoodGay(){
if(building != NULL){
delete building;
building = NULL;
}
}
};
/**
* 运算符重载:
* +号运算符重载
*/
class Person {
public:
int m_A;
int m_B;
//1.通过成员函数重载+
// Person operator+(Person &person){
// Person temp ;
// temp.m_A = this->m_A+person.m_A;
// temp.m_B = this->m_B + person.m_B;
// return temp;
// }
};
//2.通过全局函数重载+
Person operator+(Person &p1, Person &p2) {
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
//2.通过全局函数重载+
Person operator+(Person &p1, int num) {
Person temp;
temp.m_A = p1.m_A + num;
temp.m_B = p1.m_B + num;
return temp;
}
void test() {
Person p1;
Person p2;
Person p3;
p1.m_A = 10;
p1.m_B = 10;
p2.m_A = 10;
p2.m_B = 10;
p3 = p1 + p2;
cout << p3.m_A << endl;
cout << p3.m_B << endl;
Person p4;
p4 = p1 + 100; //这里可以做运算符重载。
cout << p4.m_A << endl;
cout << p4.m_B << endl;
}
int main() {
test();
return 0;
}
/**
*<<左移运算符
* >>右移运算符
*/
//左移运算符,只能通过全局函数重载。
class Person122 {
friend ostream & operator<<(ostream &cout,Person122 &p);
public:
Person122(int a,int b):m_A(a),m_B(b){
}
private :
int m_A;
int m_B;
};
ostream & operator<<(ostream &cout,Person122 &p){
cout<<"Person A:"<< p.m_A << " Person B:"<< p.m_B;
return cout;
}
void test(){
Person122 p(10,10);
cout << p <<endl;
}
int main() {
test();
return 0;
}
/**
*重载++运算符,有前置++ 和后置++
*/
class MyInteger {
friend ostream &operator<<(ostream &cout, MyInteger &myInteger);
public:
MyInteger() {
m_Num = 0;
}
//前置++操作
MyInteger & operator++(){
this->m_Num++;
return *this;
}
//后置++操作,参数中的int 占位符代表的是后置++
MyInteger operator++(int){
MyInteger temp = *this; //保存临时变量
m_Num++; //对进行++操作。
return temp;//返回临时保存的变量。
}
private:
int m_Num;
};
//重载<<左移运算符
ostream &operator<<(ostream &cout, MyInteger &myInteger) {
cout << myInteger.m_Num;
return cout;
}
void test(){
MyInteger myInteger;
cout << ++myInteger<<endl;
cout << myInteger<<endl;
}
void test01(){
MyInteger myInteger;
MyInteger myInteger1 = myInteger ++;
cout << myInteger1 <<endl;
cout << myInteger <<endl;
}
int main() {
test();
test01();
return 0;
}
//重载赋值运算符。
class Person125{
friend void test();
public:
Person125(int age){
m_Age = new int(age);
}
//重载=运算符。首先清空本身的内存,然后再申请内存。
Person125 & operator=(Person125 &p){
if(m_Age != NULL){
delete m_Age;
m_Age = NULL;
}
m_Age = new int(*p.m_Age);
return *this;
}
~Person125(){//析构函数
if(m_Age != NULL){
delete m_Age;
m_Age = NULL;
}
}
private :
int * m_Age;
};
void test(){
Person125 p1(18);
Person125 p2(28);
Person125 p3(38);
p3=p2=p1;//这里存在浅copy的问题。需要重载=运算符
cout<<*p1.m_Age<<endl;
cout<<*p2.m_Age<<endl;
cout<<*p3.m_Age<<endl;
}
int main(){
test();
return 0;
}
//关系运算符。> < != == 等等。
class Person126{
public:
Person126(string name,int age):m_Name(name),m_Age(age){
}
bool operator==(Person126 &p){
if(this->m_Name == p.m_Name && this->m_Age == p.m_Age){
return true;
}
return false;
}
bool operator!=(Person126 &p){
if(this->m_Name == p.m_Name && this->m_Age == p.m_Age){
return false;
}
return true;
}
private :
string m_Name;
int m_Age;
};
void test(){
Person126 p1("Tom",18);
Person126 p2("Tom",18);
if(p1 == p2){
cout<< "相等"<<endl;
}else{
cout<< "不相等"<<endl;
}
}
int main(){
test();
return 0;
}
//函数调用运算符重载(),也称之为仿函数,在STL中经常被使用。
//类名+() 匿名对象
class MyPrint{
public:
//这是重载(),也称之为仿函数
void operator()(string test){
cout << test<< endl;
}
};
class MyAdd{
public:
int operator()(int a,int b){
return a+ b;
}
};
int main(){
MyPrint myPrint ;
myPrint("你好");//这里使用相当于函数一样。所以称之为仿函数
//通过函数名+()的形式是匿名对象,用完即销毁。
int ret = MyAdd()(10,20);
cout << ret<<endl;
return 0;
}