重载括号运算符
语法:返回值类型 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();
}
输出: