数组
#include
int main() {
int a[5]; //在当前栈帧上为其分配内存
int* b = new int[5]; //在堆中为其分配空间
//数组的大小最好用一变量手工记录,而不是用sizeof(a)/sizeof(int) 因为这种方式有可能出错
delete[] b; // 释放堆中的数组空间
exit(0);
}
指针
#include
int main() {
char* buf = new char[8];
memset(buf, 0, 8);
delete[] buf;
std::cin.get();
}
引用
#include
#define LOG(MSG) std::cout<
类与结构体
#include
//在C++中struct和class没有太大差别
//默认struct的成员是public的,
//C++ struct 中也可以有成员方法,但通常用struct表示数据的聚合
struct Vector {
//public:
int x;
int y;
};
// class的默认访问等级是private
class Point {
public:
//为了让某个类不能被实例化,隐藏构造函数的方式有两种:
//1. 可以删除默认构造函数 用 =delete;
//2. 将其用private修饰
Point() {
}
Point(int x) = delete;
~Point() {
std::cout << "this is a destoryed func " << std::endl;
}
int x;
int y;
void setx(int newx) {
x = newx;
}
};
//m_前缀表示私有的成员变量
class Log {
public:
enum level {
LOGLEVEL_INFO = 0,
LOGLEVEL_WARNING,
LOGLEVEL_ERROR
};
private:
level m_loglevel;
public:
void setLevel(level level) { //将成员变量和传参的类型限制为枚举类型
this->m_loglevel = level;
}
void info(const char* msg) {
if (this->m_loglevel <= LOGLEVEL_INFO) {
std::cout << "[info] " << msg << std::endl;
}
}
void warn(const char* msg) {
if (this->m_loglevel <= LOGLEVEL_WARNING) {
std::cout << "[warn] " << msg << std::endl;
}
}
void error(const char* msg) {
if (this->m_loglevel <= LOGLEVEL_ERROR) {
std::cout << "[error] " << msg << std::endl;
}
}
};
int main() {
Log log;
log.setLevel(Log::LOGLEVEL_ERROR);
Point p;
log.info("hello");
log.warn("fucking");
log.error("world");
std::cin.get();//在此语句之后才会执行Point的析构函数
}
静态static
#include
//1. 在class内使用static,表示所有类的实例共享这一成员,共享同一份内存
//静态方法无法访问非静态变量
class Entity {
public:
int x, y;
static int share;
void print() {
std::cout << x << "," << y << std::endl;
}
};
void inc() {
static int i = 1;
std::cout << i++ << std::endl;
}
int Entity::share = 100;//静态成员变量需要在外部定义,并且不能在未定义的情况下直接使用
int main() {
Entity e = { 3,6 };
Entity::share = 100;
e.print();
inc();
inc();
inc();
std::cin.get();
exit(0);
}
继承
#include
//继承减少了代码重复
class Entity {// 实体类
public:
Entity() {
x = 0;
y = 0;
std::cout << "initing..." << std::endl;
}
float x, y;
void move(float a, float b) {
x += a;
y += b;
std::cout << x << "," << y << std::endl;
}
private:
int passwd;
};
class Player :public Entity {//玩家类将包含Entity所有public级别的成员
public:
int age;
char* name;
};
int main() {
Player p;//调用自己的构造函数时,将会先调用父类的构造函数
p.move(2, 3);
exit(0);
}
虚函数
#include
#include
//经常把满足某一性质、具有某种特定功能抽象成一个接口。如:Runnable Printable
class PrintNameable {
virtual void printName() = 0;
};
class Entity : public PrintNameable {
public:
int x, y;
void move(int a, int b) {
x += a;
y += b;
}
// virtual log() = 0;
virtual void print() {
std::cout << "hello Entity!" << std::endl;
}
};
class Player :public Entity {
public:
void printName() override {
std::cout << "Player" << std::endl;
}
void setName(const std::string& name) {
this->name = name;
}
void print() override {
std::cout << "hello " << this->name << std::endl;
}
// void log() override {
// std::cout << "log!!" << std::endl;
// }
private:
std::string name;
};
int main() {
//Entity e;
Entity* p = new Player();
((Player*)p)->setName("sun");//此处因为setName是子类特有的方法,必须强转为子类指针才能调用
//e.print();
p->print();
exit(0);
}
初始化列表
#include
//在任何地方都用初始化列表来对成员变量进行初始化
class Info{
public:
Info(){
std::cout<< "info is initing .."<< std::endl;
}
Info(const std::string& s){
std::cout<< "info is initing by "<< s << std::endl;
}
};
//初始化列表要求列出的成员变量的顺序必须是按照类中的声明顺序。
//并且,初始化列表是必须的。即便某个成员变量没有在初始化列表中进行初始化,编译器也会在每个构造函数的开始处调用该成员的默认构造函数:
//因此若不用初始化列表,而在函数体内进行初始化,则会造成对同一成员变量的重复初始化。
class Person{
private:
Info info;
int age;
public:
Person(const std::string& s){ // 对成员info的首次初始化:调用Info的默认构造函数
info = Info(s); //对成员info的第二次初始化
}
};
int main(){
Person *p = new Person("PP");
return 0;
}
const
#include
//1. 修饰普通变量
//2. 修饰指针,修饰引用
//3. 修饰成员方法
class Entity{
private:
int m_x,m_y;
mutable int debug_var; //显式被mutable标记的变量可以在const修饰的成员方法中被改变。
public:
int getX() const { //不能在被const修饰的方法中修改类的成员变量
debug_var++;
return m_x;
}
};
//成员函数后的const:
// 这个标志让我们能在传入参数为常对象时(eg: const myClass& e )
// 使得调用其不改变自身值的成员函数是合法的
void printX(const Entity& e ){
std::cout<< e.getX() << std::endl;
}
int main(int argc, char **argv)
{
const int MAX_SIZE = 100; //常量
int *p1 = new int;
*p1 = 200;
p1 = (int *)&MAX_SIZE; //绕过const的一种方式:将其赋值给一个非const指针
*p1 = 30;
std::cout << *p1 << std::endl;
//const 在*之前:
const int *p2 = new int;
/
class Entity{
private:
int x,y;
mutable int debug_count = 0; //第一种 mutable 的用法。
public:
Entity(){
x = 0;
y = 0;
}
const int& getx() const {
debug_count++;
return this->x;
}
};
int main(){
const Entity e; //声明为const的对象,其构造函数一定要完成对其成员变量的初始化。
std::cout << e.getx()<< std::endl;
// mutable的第二种用法
int x = 9;
auto f = [=]() mutable{
x++;
std::cout<
更多的字符类型
#include
#include
int main()
{
const wchar_t *wstr = L"long char"; //字节数不确定
const char16_t *str16 = u"2 bytes char"; //每个字符固定2字节
const char32_t *str32 = U"4 bytes char"; //每个字符固定4字节
//===============================================
//有一个方法可以让两个字符串字面量直接相加:使用字符串字面量对象:string literals
using namespace std::string_literals;
std::string res_str = "hello "s + "world!"s; //在每个字符串后加上"s" ,将其转换为字面量对象
//前缀R+括号():直接按照字面量的格式输出字符串
const char *example =
R"(line1
line2
line3)";
std::cout << example << std::endl;
exit(0);
}
字符串
#include
#include
//#define NOTDEBUG
void printString(const std::string &str);
int main()
{
const char *name = "sun"; //在GCC中 不加const的char*字符串默认为一个常量不能修改其值( 存储在常量区 )
//name[2] = 's';//会报错 可以将字符串声明为数组或是在堆上为它分配空间
std::cout << name << std::endl;
std::string name2 = "salted";
//对string进行追加操作。要对string类型变量使用+= ,而不是将两个字符串字面量相加,因为他们本质上是指针
name2 += " hello!";
std::cout << name2 << " " << name2.size() << std::endl; // 头文件中对<<操作符进行了重载!!
if (name2.find("llo") != std::string::npos) //npos 表示不存在
{
printString("found it!");
}
exit(0);
}
//关于将字符串传给函数:
//通常不会将形参写为 void printString(std::string str){} 因为这样会导致将字符串拷贝一份
//通常采用引用的方式进行传递,若此函数中的字符串时只读的,只需要在前面加上const修饰引用即可
void printString(const std::string &str)
{
#ifndef NOTDEBUG
std::cout << str << std::endl;
#else
//do nothing
#endif
}
线程
#include "tools.hpp"
#include
bool isfinshed = false;
void dosomething() {
using namespace std::chrono_literals;
std::cout << "current thread ID " << std::this_thread::get_id() << std::endl;
while (!isfinshed) {
print_lib();
std::this_thread::sleep_for(1s);
}
}
int main() {
#if 1
std::cout << "main thread ID " << std::this_thread::get_id() << std::endl;
#endif
std::thread worker(dosomething);
std::cin.get();
isfinshed = true;
worker.join();
return 0;
}