1. 如何重载成员函数?
-
函数重载: 编写多个
名称相同但参数不同
的函数 -
成员函数也可以重载
编译器根据参数数量和类型决定调用哪个构造函数
class Rectangle { public: Rectangle(int a, int b); ~Rectangle() {}; //重载成员函数Func() void Func()const; void Func(int a,int b)const; private: int a = 0; int b = 0; }; Rectangle::Rectangle(int A, int B) { a = A; b = B; } void Rectangle::Func()const { cout << "调用成员函数:void Rectangle::Func()const" ,a =" << a << " b =" << b << endl; } void Rectangle::Func(int a, int b)const { cout << "调用有参成员函数:void Rectangle::Func(int a, int b)const,a =" << a << " b =" << b << endl; } int main() { Rectangle test(2, 3); cout << "1. 成员函数:Func()" << endl; test.Func(); cout << "2. 有参成员函数:Func(int a, int b)" << endl; test.Func(5, 6); return 0; } //1. 成员函数:Func() //调用成员函数:void Rectangle::Func()const,a =2 b =3 //2. 有参成员函数:Func(int a, int b) //调用有参成员函数:void Rectangle::Func(int a, int b)const,a = 5 b = 6
-
使用默认值
代码功效与上面一样,但可读性没有上面的好,也不易维护
class Rectangle { public: Rectangle(int A, int B); ~Rectangle() {}; //使用默认值 void Func(int c, int d, bool Value)const; private: int a = 0; int b = 0; }; Rectangle::Rectangle(int A, int B) { a = A; b = B; } void Rectangle::Func(int c, int d, bool Value)const { int num1, num2; if (Value == true) { num1 = a; num2 = b; cout << "调用成员函数:void Rectangle::Func()const,a =" << a << " b =" << b << endl; } else { num1 = c; num2 = d; cout << "调用成员函数:void Rectangle::Func()const,a =" << c << " b =" << d << endl; } } int main() { Rectangle test(2, 3); cout << "1. 成员函数:Func()使用默认值" << endl; test.Func(0, 0, true); cout << "2. 成员函数:Func()" << endl; test.Func(5, 6, false); return 0; } //1. 成员函数:Func()使用默认值 //调用成员函数:void Rectangle::Func()const,a = 2 b = 3 //2. 成员函数:Func() //调用成员函数:void Rectangle::Func()const,a = 5 b = 6
-
既然可以重载函数,为何还使用默认参数值?
维护一个函数比维护两个函数容易,且理解带默认参数的函数比研究两个函数的函数体更容易(更新了一个重载函数版本,容易忽略另一个而导致bug)
-
重载函数可以有默认参数嘛?
可以。
可以有一个或多个重载函数有默认参数,规则与在常规函数中使用默认参数相同
2. 如何支持包含动态分配变量的类?
-
效率提高空间的一种简单情况:
const int num1 = 10; int num2 = 90 + num1; //100 //表达式 90 + num1 的两个组成部分都是常量,编译器将计算这个值,并存储结果100(就像把100赋值给num2)
-
函数可使用关键字 const 来返回常量值:
const int num1() { return 100; } int num2 = 90 + num1(); //190 //虽然这个成员函数 num1() 返回的是一个常量,但这个函数本身不是 const 的,它可能修改全局变量 或调用非 const 成员函数
-
常量表达式,使用关键字
constexpr
constexpr int num1() { return 100; } constexpr int num2 = 90 + num1(); //190 //常量表达式的返回值类型不能为 void,必须返回一个表达式(表达式只能包含字面值、其他常量表达式 或使用constexpr 定义的表达式)
3. 如何初始化对象?
-
构造函数也可以重载,
重载构造函数
是一种强大而灵活的功能 -
但不可以重载析构函数,
析构函数
不接受任何参数Rectangle2::Rectangle2(): a2(5),b2(6) { } //在冒号后列出要初始化的变量名(在初始化部分设置成员变量,也可以在函数体内设置)
-
由于不能给引用和常量赋值,初始化成员变量的效率比给它们赋值要高
-
尽可能在初始化部分初始化所有成员变量,有些代码必须放在构造函数的函数体内
4. 如何创建复制构造函数?
-
除了
默认构造函数
、默认析构函数
,编译器还提供一个默认复制构造函数
,每当创建对象的备份时,都将调用复制构造函数按值将对象传入或传出函数时,都将创建对象的一个临时备份。如果对象是用户定义的,就将调用相应类的复制构造函数
-
所有复制构造函数都接受一个
常量引用
作为参数,指向所属类的对象(复制函数不用修改传入的对象,const 常量引用更好)
Tricycle(const Tricycle &trike) //构造函数 Tricycle 接受一个常量引用,它指向一个现有的 Tricycle 对象 //这个复制构造函数的目标是 创建 Tricycle 对象的备份
-
复制对象时,默认复制构造函数 复制其所有成员变量
-
默认复制构造函数只是将作为参数传入的对象的每个成员变量复制到新对象中,这称为
浅复制(成员复制)
-
浅复制
将一个对象的成员变量的值复制到另一个对象中,对于大多数成员变量来说这没问题,但不适用于指向堆中对象的指针
,因为这会导致两个对象中的指针指向相同的内存地址 -
解决这种问题的方案是:自己定义复制构造函数(该构造函数接受一个参数(要复制的原始对象));并在复制时正确地分配内存(让指针指向新分配的堆内存)。
通过创建采用
深复制
的复制构造函数,将把现有值复制到新内存中class DeepCopy { public: DeepCopy(); //构造函数 DeepCopy(const DeepCopy&); //复制构造函数 ~DeepCopy(); //析构函数 int get()const { return *p; } int set(int newp) { return *p = newp; } private: int* p; }; DeepCopy::DeepCopy() //构造函数 { cout << "调用构造函数DeepCopy()" << endl; p = new int; *p = 5; } DeepCopy::DeepCopy(const DeepCopy& r) //复制构造函数 { cout << "调用复制构造函数DeepCopy(const DeepCopy& r)"<< endl; p = new int; *p = r.get(); } DeepCopy::~DeepCopy() //析构函数 { cout << "调用析构函数~DeepCopy()" << endl; delete p; p = NULL; //也可以将指针设为 0 置空,效果一样 } int main() { cout << "1. 创建DeepCopy类对象HHH " << endl; DeepCopy HHH; cout << "2. (通过调用复制构造函数并传递HHH) 创建DeepCopy类对象UUU" << endl; DeepCopy UUU(HHH); cout << "HHH.get(): " << HHH.get() << endl; cout << "UUU.get(): " << UUU.get() << endl; //将旧的 DeepCopy 类对象指向的值复制到新的 DeepCopy 类对象分配的内存中 UUU.set(10); cout << "HHH.get(): " << HHH.get() << endl; cout << "UUU.get(): " << UUU.get() << endl; //修改 UUU 不会动到 HHH,证明它们存储在不同的内存区域 return 0; } //1. 创建DeepCopy类对象HHH //调用构造函数DeepCopy() //2. (通过调用复制构造函数并传递HHH) 创建DeepCopy类对象UUU //调用复制构造函数DeepCopy(const DeepCopy & r) //HHH.get() : 5 //UUU.get() : 5 //HHH.get() : 5 //UUU.get() : 10 //调用析构函数~DeepCopy() //调用析构函数~DeepCopy()