C++

C++集锦

C++百问百答

Posted by Bob on December 19, 2018

版本

C++98(1.0)

C++03(TR1,Technical Report1)

C++11(2.0)

C++14

C++17

C++20

编译器及工具

C++ Compilers Wiki :

1.GNU Compiler Collection

2.Clang

3.Visual Studio

4.MinGW

5.Cygwin

6.Cmake

7.Scons

8.emake

9.fastbuild

const用法

const 修饰成员变量

int money = 18;

int const bank = money;

int *card = &money;

//指针所指数据是常量

const int *wechat = &money;

//指针本身是常量

int * const aiplay = &money;

//指针和指针所指数据都不能修改

const int * const bcoin = &money;

const修饰函数参数

void getMoney(const int value) {

    value = 5;//编译失败

}

const修饰成员函数


class Service {

	int money;

	void getMoney(int value) const {

		money = value;//编译失败

	}
};


const修饰函数返回值

///const data,non-const pointer

const int * getMoney(){

	int *money = new int();

	return money;

}

const int *card = getMoney();

变参的函数


#include "stdafx.h"
#include <stdio.h> 
#include <stdlib.h>
#include<stdarg.h>

void format(const char *p_format,...) {
	va_list argp;
	va_start(argp, p_format);
	const unsigned int BUFFER_SIZE = 16384;
	char buf[BUFFER_SIZE + 1];
	vsnprintf(buf, BUFFER_SIZE, p_format, argp);
	printf("%s",buf);
	va_end(argp);
};


int main()
{
	format("you are %s / %s","boy","girl");
	system("Pause");
	return 0;
}

传参数

传值 by value

//调用这个函数时先额外申请两个内存单元,存形参a和b的值1和2

void swap(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
}

int main()
{
	int m = 1;
	int n = 2;
	swap(m, n);
	system("Pause");
	return 0;
}

传址

//调用这个函数时先额外申请两个内存单元,存形参a和b的地址

void swap(int *a, int *b) {
	int temp = *a;
	*a = *b;
	*b = temp;
}

int main()
{
	int m = 1;
	int n = 2;
	swap(&m, &n);
	system("Pause");
	return 0;
}

引用 by reference

//函数时并不重新分配内存空间,形参和实参相同

void swap(int &a, int &b) {
	int temp = a;
	a = b;
	b = temp;
}

int main()
{
	int m = 1;
	int n = 2;
	swap(m, n);
	system("Pause");
	return 0;
}


虚函数

虚函数,在父类必须实现该函数; 纯虚函数,在父类中不需要实现该函数,子类必须实现。


#include <iostream>

using namespace std;

class BaseView {
public:
	BaseView() {  }
	virtual void Paint() { cout << "Paint BaseView" << endl; };
	virtual void Print() = 0;
};

class Button:BaseView {
public:
	Button() { Paint(); }
	virtual void Paint() { cout << "Paint Button" << endl; };
	virtual void Print() { cout << "Print Button" << endl; };
};


int main()
{
	Button btn;
	btn.Paint();
	system("Pause");
	return 0;
}

//结果: Paint BaseView  Paint Button Paint Button

explicit构造函数


#include <iostream>

using namespace std;

class BaseView {
public:
	int id = 0;
	explicit BaseView(int _id) { id = _id; }
};

int main()
{
	BaseView bv1(10);
	BaseView bv2 = BaseView(10);
	BaseView bv3 = 10; //编译错误  不允许隐式的转换

	system("Pause");
	return 0;
}

继承


#include <iostream>

using namespace std;

class BaseView {
public:
	BaseView() { cout << "BaseView()" << endl; };
	~BaseView() { cout << "~BaseView()" << endl; };
};

class Button:public BaseView {
public:
	Button() { cout << "Button()" << endl; };
	~Button() { cout << "~Button()" << endl; };
};


int main()
{
	Button* btn = new Button();
	delete btn;
	btn = 0;


	/*

	输出:
	
	BaseView()
	Button()
	~Button()
	~BaseView()

	*/

	system("Pause");
	return 0;
}

重载

成员函数被重载的特征:

1.相同的范围(在同一个类中); 2.函数名字相同; 3.参数不同; 4.virtual 关键字可有可无。


#include <iostream>

using namespace std;

class BaseView {
public:
	BaseView() {  }
	
};

class Button:BaseView {
public:
	Button() {  }
	void init() {};
	void init(int width, int height) {};
	void init(int width, int height,int length) {};
};


int main()
{
	Button btn;
	system("Pause");
	return 0;
}

覆盖

覆盖是指子类函数覆盖父类函数,特征是:

1.不同的范围(分别位于子类与父类); 2.函数名字相同; 3.参数相同; 4.基类函数必须有virtual 关键字。



#include <iostream>

using namespace std;

class BaseView {
public:
	BaseView() {  }
	virtual void init(int width, int height) { cout << "BaseView.init(int width, int height)" << endl; };
};

class Button:BaseView {
public:
	Button() {  }
	void init(int width, int height) { cout << "Button.init(int width, int height)" << endl; };
	
};


int main()
{
	Button btn;
	btn.init(10,20);
	system("Pause");
	return 0;
}

//结果:Button.init(int width, int height)

隐藏

如果子类的函数与父类的函数同名,并且参数也相同,但是父类函数没有virtual关键字。此时,父类的函数被隐藏(注意别与覆盖混淆)。



#include <iostream>

using namespace std;

class BaseView {
public:
	BaseView() {  }
	void init(int width, int height) { cout << "BaseView.init(int width, int height)" << endl; };
};

class Button:BaseView {
public:
	Button() {  }
	void init(int width, int height) { cout << "Button.init(int width, int height)" << endl; };
	
};


int main()
{
	Button btn;
	btn.init(10,20);
	system("Pause");
	return 0;
}

//结果:Button.init(int width, int height)

隐藏

如果子类的函数与父类的函数同名,但是参数不同。此时,不论有无virtual关键字,父类的函数将被隐藏(注意别与重载混淆)


#include <iostream>

using namespace std;

class BaseView {
public:
	void init(int width, int height) { cout << "BaseView.init(int width, int height)" << endl; };
	virtual void resetSize(int width, int height) { cout << "BaseView.resetSize(int width, int height)" << endl; };
	virtual void resetPos(int x, int y) { cout << "BaseView.resetPos(int x, int y)" << endl; };
};

class Button:public BaseView {
public:
	void init(float width, float height) { cout << "Button.init(float width, float height)" << endl; };
	virtual void resetSize(float width, float height) { cout << "Button.resetSize(float width, float height)" << endl; };
	virtual void resetPos(int x, int y) { cout << "Button.resetPos(int x, int y)" << endl; };
};


int main()
{
	Button btn;
	btn.init(10, 20);
	btn.resetSize(10, 20);
	btn.resetPos(10,20);



	Button btn2;
	BaseView *bptr1 = &btn2;
	Button *bptr2 = &btn2;

	//bad
	bptr1->init(10, 20);
	bptr2->init(10,20);

	//bad
	bptr1->resetSize(10, 20);
	bptr2->resetSize(10, 20);

	//good
	bptr1->resetPos(10, 20);
	bptr2->resetPos(10, 20);


	/*

	结果:
	Button.init(float width, float height)
	Button.resetSize(float width, float height)
	Button.resetPos(int x, int y)

	BaseView.init(int width, int height)
	Button.init(float width, float height)

	BaseView.resetSize(int width, int height)
	Button.resetSize(float width, float height)

	Button.resetPos(int x, int y)
	Button.resetPos(int x, int y)

	*/

	system("Pause");
	return 0;
}