C++面向对象高级编程
- 1 inline-内联函数
- 1.1 什么是内联函数?
- 1.2 为什么需要内联函数?
- 2 构造函数
- 2.1 构造函数是什么?
- 2.2 为什么需要构造函数?
- 2.3 ctor(构造函数)可以有很多个-overloading重载
- 2.4 ctors放在private区-Singleton
- 3 参数传递与返回值
- 3.1 参数传递:值传递 vs. 引用传递 (to const)
- 3.2 返回值传递:值传递 vs. 引用传递 (to const)
- 4 friend(友元)
- 5 操作符重载(operator overloading)-1,成员函数——this
1 inline-内联函数
1.1 什么是内联函数?
如果某个函数(只有一两行语句)前面加上“inline”的关键字,则该函数被称为内联函数。在编译时,在函数被调用的地方将会被替换成该函数体。
1.2 为什么需要内联函数?
主要是为了解决一些频繁调用的小函数大量消耗栈内存的问题。
2 构造函数
class complex {
public:
complex(double r = 0, double i = 0)
: re(r), im(i)
{ }
complex& operator += (const complex&);
double real() const { return re; }
double imag() const { return im; } //class内置函数,默认是inline
private:
//T re, im;
double re, im;
friend complex& __doapl(complex*, const complex&);
};
2.1 构造函数是什么?
complex类的构造函数主要是以下三行语句:
complex(double r = 0, double i = 0)
: re(r), im(i)
{ }
在创建对象时,我们可以调用构造函数:
complex c1(2, 1);
complex c2;
complex* p = new complex(4);
2.2 为什么需要构造函数?
中间行是initialization list(初值列,初始列),实际上就是对re和im进行初始化并进行初始值的赋值。虽然我们在{ }内进行赋值也可以,但是这样就“放弃”了初始化的阶段,虽然最后还是把值放进去了,但是时间点完了,效率也会低一点。
2.3 ctor(构造函数)可以有很多个-overloading重载
重载的意思是说,c++允许多个同名的函数存在,比如说下面两个函数:
double real () const { return re; }
void real(double r ) { re = r; }
他们的名称是一样的,但是对于编译器来说,他们经过编译后的实际名称是不一样的。所以他们可以同时存在,因为编译器知道当他遇到这个名称的函数时自己要调用哪一个函数。
但是对于构造函数来说,下面这种情况是不允许的:
complex (double r = 0; double i = 0)
: re (r), im (i)
{ }
complex () : re (0), im (0) { }
complex c1;
complex c2();
因为上面的构造函数具有默认参数,两种构造函数都可以用上面两种方式被调用,对于编辑器来说,他就不知道到底要调用哪一个构造函数。
2.4 ctors放在private区-Singleton
class A{
public:
static A& getInstance();
setup() {...}
private:
A();
A(const A& rhs);
...
};
A& A::getInstance(){
static A a;
return a;
}
当构造函数放在private里时,说明它只能被创造一次(已经在类中创建好了),需要使用时调用类的getInstance()
函数获取它。
3 参数传递与返回值
3.1 参数传递:值传递 vs. 引用传递 (to const)
值传递不能改变原始变量的值,引用传递可以改变(const除外)。在可以的情况下,尽量都使用引用传递函数参数。
下面是引用传递的一个例子:
#include <iostream>
void changeValue(int& numRef) {
numRef = 5;
}
int main() {
int num = 10;
changeValue(num);
std::cout << num << std::endl; // 输出结果为5,原始值被修改
return 0;
}
3.2 返回值传递:值传递 vs. 引用传递 (to const)
需要注意的是,使用引用传递返回值时,这个引用是否还有效?如果当一个函数结束,引用的空间被销毁,那么传出去的东西就是坏的。
4 friend(友元)
class complex
{
...
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
}
inline complex& doapl (complex* ths, const complex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
}
友元函数可以自由取得这个类中的private成员。
相同class的各个object互为友元。可以看到下面例子中c2可以直接获得c1中的private成员:
class complex{
public:
complex (double r=0, double i=0)
: re (r), im (i)
{ }
int func(const complex& param){
return param.re + param.im;
}
private:
double re, im;
};
...
{
complex c1(2, 1);
complex c2;
c2.func(c1);
}
5 操作符重载(operator overloading)-1,成员函数——this
inline complex& __doapl(complex* ths, const complex& r){
ths->re += r.re;
ths->im += r.im;
return *ths;
}
inline complex& complex:: operator += (const complex& r){
return __doapl(this, r);
}
{
complex c1(2, 1);
complex c2(5);
c2 += c1;
}
当编译器看到使用“+=”这个操作符时,它是作用在左边的成员身上的,也就是“c2”。如果“c2”有对这个操作符做定义的话,那么编译器就可以执行定义的相关操作,也就是下面这个函数:
inline complex& complex:: operator += (this, const complex& r){
return __doapl(this, r);
}
可以发现我在重写这个函数时,参数中多了一个“this”,但实际上代码中是没有的(不能写出来)。“this”是一个指针,它代表的是调用这个函数的成员变量,也就是“c2”。那么“r”就是“c1”。