浙大 C++
本机环境
> g++ -v
Apple clang version 14.0.3 (clang-1403.0.22.14.1)
Target: x86_64-apple-darwin22.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
对象组合
- Objects can be used to build up other objects.
- Ways of inclusion
- Fully
- By reference
- Inclusion by reference allows sharing
class Person{};
class Currency{};
class SavingsAccount{
private:
Person m_saver;
SavingsAccount m_balance;
public:
SavingsAccount(const char* account_num, int cents);
~SavingsAccount();
void print();
};
// 初始化列表方式赋初值
SavingsAccount::SavingsAccount(const char* account_num, int cents):m_saver(account_num),m_balance(0, cents){}
void SavingsAccount::print(){
m_saver.print();
m_balance.print();
}
继承
- Reusing the interface
Inheriance is to take the existing class, clone it, and then make additions and modifications to the clone.
- Inheriance
- Language implementation technique
- Also an important component of the OO design methodology.
- Allows sharing of design for
- Member data
- Member functions
- Interfaces
- Key technology in c++
- 案例
class A{
private:
int data;
public:
A():data(0){cout << "A::A()" << endl;};
~A(){cout << "A::~A()" << endl;}
void print() { cout << "data=" << data << endl;};
protected:
void set(int d){data=d;}
};
class B : public A{
public:
void f(){set(100);print();}
};
int main(void) {
B b;
//b.set(99); error
b.f();
return 0;
}
子类父类关系
子类父类构造与析构的执行顺序
class A{
private:
int data;
public:
A(int i):data(i){cout << "A::A()" << endl;};
~A(){cout << "A::~A()" << endl;}
void print() { cout << "data=" << data << endl;};
void print(int i) { cout << i; print();}; // 重载
protected:
void set(int d){data=d;}
};
class B : public A{
public:
B():A(0){cout << "B::B()" << endl;};
~B(){cout << "B::~B()" << endl;}
void f(){set(100);print();}
void print() { cout << "B::print()" << endl;}; // 重写
// 重写后就不能再使用父类的`同名函数以及同名函数的重载函数`
// 只有C++是这么做的
// 这种机制叫做 name hiding
// https://blog.csdn.net/wangdingqiaoit/article/details/46502399
};
int main(void) {
B b;
b.print();
// b.print(111); error
b.A::print();
b.A::print(111);
return 0;
}
函数缺省参数值
不推荐使用 default value(即 函数缺省值)
// 缺省值写在声明里即可,不用在定义里写了
int harpo(int k, int m = 2,int n = 3);
int groucho(int k = 1, int m = 2,int n = 3);
// int chico(int k, int m = 2,int n); error
// 必须从右往左依次设置缺省值
int groucho(int k, int m,int n){
return k + m + n;
}
int main(void) {
cout << groucho(3, 3) << endl;
return 0;
}
内联函数
- Overhead for a function call
- the processing time required by a device prior to the execution of a command
- Push parameters
- Push return address
- Prepare return values
- Pop all pushed
堆栈模型(入栈/出栈)
由于调用一个函数的需要很多额外的操作,c++层面提供了一种优化方案:内联函数
- Inline Functions
An inline function is expanded in place ,like a preprocessor macro ,so the overhead of the function call is eliminated. 内联函数像预处理器宏一样就地扩展,因此消除了函数调用的开销。
int f(int i){return i*2;}
int main(){
int a = 4;
int b = f(a); // 会有函数调用过程
return 0;
}
使用内联函数优化
inline int f(int i){return i*2;}
int main(){
int a = 4;
int b = f(a); // 不会有函数调用过程
return 0;
}
// 等价于
int main(){
int a = 4;
int b = a * 2;
return 0;
}
- Inline Functions 使用说明
// a.h
inline int plusOne(int x);
inline int plusOne(int x){return ++x;}
- Repeat
inline
keyword atdeclaration
anddefinition
. - An inline function definition may not generate any code in
.obj
file.
- 一般来说会把内联函数的声明和定义都放到同一个头文件里。
- 若满足上诉条件,则只有定义语句也是可以的。
// a.h
inline int plusOne(int x){return ++x;}
- Inline functions in header file
- So you can put inline functions bodies in header file. Then #include it where the function is needed.
- Never be afraid of multi-definition of inline functions, since they have no body at all.
- Definitions of inline functions are just declarations.
- Tradeoff of inline functions (内联函数的权衡)
- Body of the called function is to be inserted into the caller.
- This may expand the code size.
- but deduces the overhead of calling time
- So it gains speed at the expenses of space
- In most cases, it is worth.
- It is much better than macro in C .It checks the types of the parameters.
- Inline may be not in-line
The compiler does not have to honor your request to make a function inline. It might decide the function is too large or notice that it calls itself (recursion is not allowed or indeed possible for inline functions), or the feature might not be implemented for your particular compiler.
- Inline inside classes
- Any function you define inside a class declaration is automatically an inline.
- (成员函数如果在class声明的时候就给出了body,那些函数自动成为内联函数)
// a.h
class A{
public:
A(){ cout << "A()";} // 内联函数
f(){ cout << "f()";} // 内联函数
print();
}
A::print(){}
- Access functions
They are small functions that allow you to read or change part of the state of an object - that is , an interal variable or variables.
// a.h
class Cup{
int color;
public:
int getColor(){return color;}
void setColor(int color){this->color=color;}
}
- Reducing clutter
Member functions defined within classes use the Latin in situ (in place) and maintains that all definitions should be placed outside the class to keep the interface clean.
// a.h
class A{
public:
A(){ cout << "A()";} // 内联函数
f(){ cout << "f()";} // 内联函数
print(); // 内联函数,因为函数body有inline声明,且保持了类定义的清晰度
}
inline A::print(){}
- Inline or not?
- Inline
- Small functions, 2 or 3 lines;
- Frequently called functions, e.g. inside loops
- Not Inline
- Very large functions ,more than 20 lines
- Recursive functions