Stories About C Plus Plus

🧀 Knowing, learning and mastering c++ is a cool thing in my opinion. Like a chef with a handy kitchen knife, you can do a lot of interesting things with c++. This learning note is mainly about some c++ points. Wish myself an early glimpse of c++.

static

this指针

inline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//inline.h
#ifndef BASE_INLINE_H
#define BASE_INLINE_H

class A
{
public:
int foo1(int x, int y);


void Foo(int x, int y)
{

};
void f1(int x);
};

#endif //BASE_INLINE_H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

#include <iostream>
#include "inline.h"

using namespace std;

int Foo(int x, int y);
inline int Foo(int x, int y)
{
return x + y;
}

//定义处添加inline(显示声明)推荐

inline void A::f1(int x)
{

}

int main()
{
cout << Foo(1,2) << endl;
}

声明方式

inline 对编译器来说是一条指令而非命令,可以显示声明可以隐式声明。

显示声明:==inline==修饰符

1
2
3
4
5
6
int foo(int x, int y); //函数声明
inline int foo(int x, int y) // 函数定义
{
return x + y;
}

隐式声明:类中方法的定义

1
2
3
4
5
class A
{
public:
int foo1(int x, int y); //隐式声明
}

使用场景

首先了解编译器对inline的处理

  1. 将inline函数体复制到调用处
  2. 为inline函数中的局部变量分配内存空间
  3. 将inline函数的输入参数和返回值映射到调用方法的局部空间中
  4. inline若有多个返回点将其转变为 inline 函数代码块末尾的分支(使用 GOTO)

内联函数能够提高函数效率,实质上就是将函数直接复制,一耗费更过空间为代价省去了函数调用的开销。提高函数执行效率。以下场景不适合使用

  • 函数代码执行时间相比于函数调用花费时间长
  • 函数代码段较长,函数体内出现循环。

虚函数的vptr与vtable

一个例子是当一个中断服务子程序修该一个指向一个buffer的指针时

//todo

assert 断言

  • 断言是宏在<assert.h>头文件中,而非函数。

  • 通过定义NDEBUG关闭assert,定义在源码开头,#include<assert.h>之前

为何使用/与正常错误处理

  • 断言用于检查逻辑上不可能的情况如:检查源码在运行前期望的状态或者在运行完成后的检查状态
  • 与正常错误处理不同断言通常在运行时被禁用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//#define NDEBUG      定义后assert不可用
#include <iostream>
#include <assert.h>

using namespace std;

int main()
{
int x = 7;

//some code

x = 9;

//some code
assert(x==7);

return 0;
}

extern”c” and extern “C++”

extern 用于c++ 链接c语言中定义的函数

在编译阶段,c++编译生成的文件中可能有些符号与C语言生成的不同,比如c++中的重载,多态等。extern的作用便是:告诉链接器去寻找c语言符号而不是经过c++修饰后的符号

``先看一个错误的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//add.h
#ifdef BASE_ADD_H
extern "C" {
#endif
int add(int x, int y);

#ifdef BASE_ADD_H
}
#endif //BASE_ADD_H

//add.c
#include <stdio.h>
#include "add.h"
int add(int x, int y){
return x + y;
}

//add.cpp
#include <iostream>
using namespace std;
extern "C"{
#include "add.h"
}

int main()
{
add(2,3);
return 0;
}

error: ‘add’ was not declared in this scope

在stdio.h标准库中

1
2
3
#ifdef __cplusplus
extern "C" {
#endif

c++ 在调用接口时以C接口调用。这种写法使得c++在调用时不需要额外写externa “C”

C与C++中struct的区别

C C++
结构体中无函数 可有函数
无访问修饰符,默认public protect, private,public
定义的结构体变量,使用时必须加上 struct 可不加
无继承 可继承
若结构体的名字与函数名相同,可以正常运行且正常的调用 若结构体的名字与函数名相同,使用结构体,只能使用带struct定义

friend

友元函数:可以理解为静态函数,需单独实现,能够访问类的私有和保护成员
友元类: 同理见实例

特点

破坏了封装性,提高了运行效率

一些性质

  • 不可传递性: A是B的友元类,B是C的友元类,A不是C的友元类
  • 无继承性: B是A的友元类,C继承A,C无法访问B的私有和保护成员
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

using namespace std;

class A{
public:
A(int _a):a(_a){};
friend int geta(A a);

friend class B; //B是A的友元类,
private:
int a;
};

int geta(A a){
return a.a;
}

class B{
public:
int getb(A _a){
return _a.a;
}
};
int main()
{
A a{2};
B b;
cout << "geta:\t" << geta(a) <<endl;
cout << "getb:\t" << b.getb(a) << endl;
return 0;
}

:: 作用域

声明作用域

  • 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间
  • 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的
  • 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//From Light-City
#include <iostream>
using namespace std;

int count=0; // 全局(::)的count

class A {
public:
static int count; // 类A的count (A::count)

};
// 静态变量必须在此处定义
int A::count;
int main() {
::count=1; // 设置全局的count为1
A::count=5; // 设置类A的count为2
cout<<A::count<<endl;
// int count=3; // 局部count
// count=4; // 设置局部的count为4
return 0;
}

Reference

Light-City/CPlusPlusThings

Comments