C++笔记

本文详细介绍了如何在C++中重载括号运算符,将其作为函数对象使用,以及拷贝构造函数的工作原理、作用域规则、私有继承和派生类中的成员访问。还展示了如何自定义拷贝构造函数及其重载,以及拷贝构造函数在不同情况下的调用行为。
摘要由CSDN通过智能技术生成

重载括号运算符

语法:返回值类型 operator()(参数列表)

【函数返回值爱用什么用什么,参数列表想写多少写多少】

括号运算符()可以重载,对象名可当成函数来使用(函数对象,仿函数)

注:  

1.括号运算符必须以成员函数的形式进行重载

2.括号运算符重载函数具备普通函数全部的特征

3.函数对象与全局函数同名,按作用域规则选择调用的函数  ::

下面代码讲述3中作用域的使用

#include<iostream>
using namespace std;
void show(string str) {
    cout << "普通函数:" << str << endl;
}
class Cgirl {
public:
    void operator()(string str) {
        cout << "重载函数:" <<str<< endl;
     }
};
int main() {
    Cgirl show;
    // ::show("我是一只傻傻鸟");
    show("我是一个小小鸟");
    show("我是一个傻傻鸟");
    return 0;
}

未用作用域结果

 用了作用域结果

 继承

类成员权限由高到低依次:public --> protected --> private

私有继承代码样例:

#include<iostream>
using namespace std;
#include<unordered_set>
#include<iomanip>

class CAIIComers {
public:
	string m_name;
	string m_tel;
protected:
	int m_a;
private:
	int m_b;
public:
	//构造函数
	CAIIComers() {
		m_name = "二哈";
		m_tel = "不到";
	}
	void sing() { cout << "你是一只鸟\n"; }
	void setname(const string& name) { m_name = name; }
	void settel(const string& tel) { m_tel = tel; }

};
// m_name m_tel m_a 将成为超女类的私有成员
class Cgirl : private CAIIComers {
public:
	int m_bh;
	Cgirl(){ m_bh = 8; }
	void show() {
		setname("冰冰");  //上面类的非私有成员在Cgirl类的成员函数中可以访问,但是在main函数中不能访问 
		// 应该是私有继承的关系 private
		cout << "编号:" << m_bh << "姓名:" << m_name << "联系电话:" << m_tel << endl;
	}
};

int main() {
	Cgirl g;
	// g.setname("冰冰");
	g.show();
}

派生类中可以通过基类的公有成员函数间接访问基类的私有成员。

使用using关键字可以改变基类成员在派生类中的访问权限。

拷贝构造函数

用一个已存在的对象创建新的对象,不会调用(普通)构造函数,而是调用拷贝构造函数。

若类中没有定义拷贝构造函数,编译器将提供一个拷贝构造函数,他的功能是把已存在对象的成员变量赋值给新对象的成员变量。

已存在对象创建新对象语法

类名 新对象名(已存在的对象名);

类名 新对象名=已存在的对象名;

#include<vector>
#include<iostream>
using namespace std;

class Cgirl {
public:
	string m_name;
	int m_age;
	Cgirl() { m_name.clear(); m_age = 0; cout << "调用了构造函数\n"; }
	~Cgirl() { cout << "调用了析构函数\n"; }

	void show() {
		cout << "m_name:" << m_name << ",m_age:" << m_age << endl;
	}
};

int main() {
	Cgirl g1;
	g1.m_name = "冰冰"; g1.m_age = 23;
	Cgirl g2(g1);  // 对象构造新对象
	g2.show();
}

结果:

 拷贝构造函数的语法:

类名(const 类名& 对象名){.....}

自个写了拷贝构造函数,就会调用自个写的,代码如下:

#include<vector>
#include<iostream>
using namespace std;

class Cgirl {
public:
	string m_name;
	int m_age;
	// 无参数的普通构造函数
	Cgirl() { m_name.clear(); m_age = 0; cout << "调用了构造函数\n"; }

	//没有重载的拷贝构造函数(默认拷贝构造函数) 也可以在里面加点其他的东西
	Cgirl(const Cgirl& gg) { m_name = "好哇塞的" + gg.m_name;m_age = gg.m_age -1; cout << "调用了拷贝构造函数。\n"; }
	// Cgirl(const Cgirl& gg) { m_name.clear(); m_age = 0; cout << "调用了拷贝构造函数。\n"; }

	// 析构函数
	~Cgirl() { cout << "调用了析构函数\n"; }

	//
	void show() {
		cout << "m_name:" << m_name << ",m_age:" << m_age << endl;
	}
};

int main() {
	Cgirl g1;
	g1.m_name = "冰冰"; g1.m_age = 23;
	Cgirl g2(g1);  // 对象构造新对象
	g2.show();
}

结果如下:

 以值传递的方式调用函数时,若实参为对象,会调用拷贝构造函数

#include<vector>
#include<iostream>
using namespace std;

class Cgirl {
public:
	string m_name;
	int m_age;
	// 无参数的普通构造函数
	Cgirl() { m_name.clear(); m_age = 0; cout << "调用了构造函数\n"; }

	//没有重载的拷贝构造函数(默认拷贝构造函数) 也可以在里面加点其他的东西
	Cgirl(const Cgirl& gg) { m_name = "好哇塞的" + gg.m_name;m_age = gg.m_age -1; cout << "调用了拷贝构造函数。\n"; }
	// Cgirl(const Cgirl& gg) { m_name.clear(); m_age = 0; cout << "调用了拷贝构造函数。\n"; }

	// 析构函数
	~Cgirl() { cout << "调用了析构函数\n"; }

	//
	void show() {
		cout << "m_name:" << m_name << ",m_age:" << m_age << endl;
	}
};

void func(Cgirl g) {
	g.show();
}

int main() {
	Cgirl g1;
	g1.m_name = "冰冰"; g1.m_age = 23;
	func(g1);
}

 函数以值得方式返回对象时,可能会调用拷贝构造函数(vs会,Linux不会,g++编译做了优化)

下面是vs中的,但是没有调用拷贝构造函数,很奇怪,不知道哪里出问题了,按道理来说应该是走拷贝构造函数的:

#include<vector>
#include<iostream>
using namespace std;
class Cgirl {
public:
	string m_name;
	int m_age;
	// 无参数的普通构造函数
	Cgirl() { m_name.clear(); m_age = 0; cout << "调用了构造函数\n"; }
	//没有重载的拷贝构造函数(默认拷贝构造函数) 也可以在里面加点其他的东西
	Cgirl(const Cgirl& gg) { m_name = "好哇塞的" + gg.m_name;m_age = gg.m_age -1; cout << "调用了拷贝构造函数。\n"; }
	// Cgirl(const Cgirl& gg) { m_name.clear(); m_age = 0; cout << "调用了拷贝构造函数。\n"; }

	// 析构函数
	~Cgirl() { cout << "调用了析构函数\n"; }
	
	void show() {
		cout << "m_name:" << m_name << ",m_age:" << m_age << endl;
	}
};
Cgirl func() {
	Cgirl gg;
	gg.m_name = "小磊"; gg.m_age = 23;
	return gg;
}
int main() {
	Cgirl g = func();
	g.show();
}

加了日志之后输出两个地址是一样的,好奇怪欸。。。

拷贝构造函数可以重载,可以有默认参数,但是重载的时候,形参中一定要有类本身的常引用

若没有类本身常应用,那就成为普通构造函数了 对吧!

类名(...,const 类名& 对象名,....){....}

来来来,看一看重载的拷贝构造函数

#include<vector>
#include<iostream>
using namespace std;
class Cgirl {
public:
	string m_name;
	int m_age;
	// 无参数的普通构造函数
	Cgirl() { m_name.clear(); m_age = 0; cout << "调用了构造函数\n"; }
	//没有重载的拷贝构造函数(默认拷贝构造函数) 也可以在里面加点其他的东西
	Cgirl(const Cgirl& gg) { m_name = "好哇塞的" + gg.m_name;m_age = gg.m_age -1; cout << "调用了没有重载的拷贝构造函数。\n"; }
	// Cgirl(const Cgirl& gg) { m_name.clear(); m_age = 0; cout << "调用了拷贝构造函数。\n"; }
	//重载的拷贝构造函数
	Cgirl(const Cgirl& gg, int ii) { m_name = "好哇塞的" + gg.m_name; m_age = gg.m_age - 1; cout << "调用了重载的拷贝构造函数。\n"; }

	// 析构函数
	~Cgirl() { cout << "调用了析构函数\n"; }
	
	void show() {
		cout << "m_name:" << m_name << ",m_age:" << m_age << endl;
	}
};

int main() {
	Cgirl g1;
	g1.m_name = "竟博"; g1.m_age = 80;
	Cgirl g2(g1,3);
	g2.show();
}

 输出:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值