基本语法:
class Student
{
string name;
string sId;
public:
Student(string n, string s)
{
name = n;
sId = s;
};
void print()
{
cout << name << "," << sId << endl;
}
};
访问权限:public,protected,private 类似java。
struct 默认权限为public,class 默认权限为private。
class Person
{
public:
Person()
{
cout << "person" << endl;
}
// 析构
~Person()
{
cout << "~person" << endl;
}
};
//拷贝构造
Person(const Person &p)
{
age = p.age;
}
// 值传递给一个函数参数传值,值方式返回局部对象
调用方式:括号、显示、隐式转换
Person p;
person p1(10);
Person p2 = Person(10);
Person p3 = 10;// Person p = Person(10)
// 匿名对象
// 当前执行结束后,立刻销毁
// 不要用拷贝构造函数 初始化匿名对象
Person(p3);//Error
C++拷贝构造函数调用时机
构造函数创建规则
默认情况C++编译器个一个类至少有添加三个函数:默认构造,拷贝函数,析构函数
浅拷贝:编译器默认提供给的拷贝构造函数,主要做了赋值操作
出现问题:指针指向同一块内存地址,堆区内存重复释放
深拷贝:重新在堆区申请空间
解决浅拷贝问题:自己实现拷贝构造,给指针变量重新申请空间
this指针
本质是指针常量,不可修改指针的指向
class Person
{
string m_Name;
public:
void printName()
{
cout << m_Name << endl;
}
void printAny()
{
cout << "Any" << endl;
}
};
...
Person* p1 = NULL;
p1->printAny();
p1->printName();// ERROR
class Person
{
string m_Name;
public:
// 常函数内部不可修改成员属性,若加mutable 修饰则可修改
void func() const
{
//this = NULL;//ERROR "this" is "Person* contst this" ;
//this->m_Name = "11";// ERROR 常函数 is "const Person* contst this"
}
};
const Person p;// 常对象只能调用常函数
访问类得私有成员
class Building
{
friend void goodGay(Building& b);// 全局函数做友元
friend class GoodGay;// 类做友元
public :
string m_CustomerRoom;
Building()
{
m_CustomerRoom = "客厅";
m_BedRoom = "卧室";
}
private:
string m_BedRoom;
};
class GoodGay
{
public :
GoodGay();
void visit();
private :
Building* b;
};
GoodGay::GoodGay()
{
b = new Building;
}
void GoodGay::visit()
{
cout << b->m_BedRoom<
operator+
operator()
class MyInteger
{
public:
int m_Age;
MyInteger operator+ (MyInteger &a) {
this->m_Age += a.m_Age;
return *this;
}
};
...
MyInteger a1;
MyInteger a2;
MyInteger a3 = a1 + a2;
class Dog : Anim
{
};
class Anim
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Dog :protected Anim
{
int m_D;
};
...
Dog d;
cout << sizeof(d) << endl;// 16
查看对象模型语句:cl /d1 reportSingleClassLayoutDog main.cpp
class Dog size(16):
+---
0 | +--- (base class Anim)
0 | | m_A
4 | | m_B
8 | | m_C
| +---
12 | m_D
+---
***继承中先调用父类构造函数在调用子类构造函数,析构顺序相反***
继承关系中同名成员如何处理
class Anim
{
public:
int m_A = 0;
void func()
{
cout << "Anim Func" << endl;
}
};
class Dog :public Anim
{
public:
int m_A = 1;
void func()
{
cout << "Dog Func" << endl;
}
};
...
Dog d;
cout << "Dog Class:" << d.m_A << endl;
cout << "Anim Class:" << d.Anim::m_A << endl;
d.func();
d.Anim::func();
语法:class 子类 : 继承方式 父类,继承方式 父类
问题:多继承引发同名成员,二义性问题,需要加作用域,不太建议使用;
class Dog :public Anim1,public Anim2
{
public:
int m_A = 1;
void func()
{
cout << "Dog Func" << endl;
}
};
介绍:需要继承的父类只存在一份
方案:利用虚继承,vbprt 虚基类指针指向虚基类表,能找到同一块内存空间
class Anim
{
public:
int m_Age;
};
class Cat :virtual public Anim{};
class Dog :virtual public Anim{};
class FaimalyAnim :public Cat, public Dog {};
...
FaimalyAnim f;
f.Cat::m_Age = 19;
f.Dog::m_Age = 28;
cout << "cat:" << f.Cat::m_Age << endl;// 28
cout << "dog:" << f.Dog::m_Age << endl;// 28
内存模型
未使用虚继承的内存模型
class FaimalyAnim size(8):
+---
0 | +--- (base class Cat)
0 | | +--- (base class Anim)
0 | | | m_Age
| | +---
| +---
4 | +--- (base class Dog)
4 | | +--- (base class Anim)
4 | | | m_Age
| | +---
| +---
+---
使用虚继承后的内存模型
class Anim
{
public:
int m_Age;
};
class Cat :virtual public Anim{};
class Dog :virtual public Anim{};
class FaimalyAnim :public Cat, public Dog {};
class FaimalyAnim size(12):
+---
0 | +--- (base class Cat)
0 | | {vbptr}// v-virtual b- ptr-pointer
| +---
4 | +--- (base class Dog)
4 | | {vbptr}
| +---
+---
+--- (virtual base Anim)
8 | m_Age
+---
FaimalyAnim::$vbtable@Cat@:
0 | 0
1 | 8 (FaimalyAnimd(Cat+0)Anim)
FaimalyAnim::$vbtable@Dog@:
0 | 0
1 | 4 (FaimalyAnimd(Dog+0)Anim)
vbi: class offset o.vbptr o.vbte fVtorDisp
Anim 8 0 4 0
动态多态:有继承关系,子类重写父类虚函数
class Anim
{
public:
int m_Age;
// 虚函数
virtual void speak()
{
cout << "anim speak" << endl;
}
};
class Cat :public Anim{
void speak()
{
cout << "Cat speak" << endl;
}
};
class Dog :public Anim{
void speak()
{
cout << "Dog speak" << endl;
}
};
//地址晚绑定
void doSpeak(Anim &a) // 父类的指针或者引用指向子类对象 Anim &a = Cat
{
a.speak();
}
父类中使用虚函数
class Anim
{
public:
Anim(){
speak();// 不会走父类的实现
eat();// 报错,因为此时子类还未创建
}
int m_Age;
// 虚函数
virtual void speak()
{
cout << "anim speak" << endl;
}
//纯虚函数
virtual void eat() = 0;
};
class Anim size(8):
+---
0 | {vfptr}
4 | m_Age
+---
Anim::$vftable@:
| &Anim_meta
| 0
0 | &Anim::speak
Anim::speak this adjustor: 0
纯虚函数,子类需要重写父类的纯虚函数,否则即是抽象类,无法实例化
class Base
{
public:
virtual void func() = 0;
};
// 父类指针在析构的时候,不会调用子类的析构函数,导致子类如果有堆区属性,出现内存泄漏
方案:把父类析构改为虚析构
// 写文件
void test01()
{
ofstream ofs;
ofs.open("demo.txt", ios::out);
ofs << "Name:Picher" << endl;
ofs << "Age:26" << endl;
ofs << "Area:Hubei" << endl;
ofs.close();
}
//读文件
void test02()
{
ifstream ifs;
//方法一
ifs.open("demo.txt",ios::in);
char buff[1024] = {};
/*while (ifs >> buff)
{
cout << buff << endl;
}*/
//方法二
/*while (ifs.getline(buff,sizeof(buff)))
{
cout << buff << endl;
}*/
//方法三
/*string buf;
while (getline(ifs, buf))
{
cout << buf << endl;
}*/
//方法四
char c;
while ((c = ifs.get()) != EOF)
{
cout << c;
}
ifs.close();
}
template
函数声明或定义
模板的局限性:自定义类无法自动识别
template
bool compare(T& a, T& b)
{
return a == b;
}
...
Person p1;
Person p2;
cout << compare(p1, p2) << endl; // ERROR
template
类
类模板中成员函数创建时机:调用时才创建
template
class Student
{
public:
T data;
};
// 1. 指定数据类型
void func(Student& s)
{
cout << s.data << endl;
}
// 2. 参数模板化
template
void func1(Student& s)
{
cout << s.data << endl;
}
// 3. 整个类模板化
template
void func2(T& s)
{
cout << s.data << endl;
}
template
class Base
{
Base(T age);
void printAge();
T m_Age;
};
template
class Son :public Base
{
T m_Name;
};
template
Base::Base(T age)
{
this->m_Age = age;
}
// 类外实现
template
void Base::printAge()
{
cout << this->m_Age << endl;
}
类似Java代码:
public abstract class Base<T>{
abstract Base(T age);
abstract void printAge();
T m_Age;
}
public class Son<T> extents Base<Integer>{
T mName;
}
...
容器、算法、迭代器、仿函数、适配器、空间配置器
rfind与find区别:rfind从右往左查,find从左往右查
//string 操作,类似java
void test03()
{
string s = "Hello,Word!";
int pos = s.find("Word");
// 查找
cout << "find:" << pos << endl;
cout << "rfind:" << s.rfind("Word") << endl;
// 替换
s = s.replace(pos, s.length(), "picher");
cout << "replace:" << s << endl;
// 剪裁
s = s.substr(0, pos);
cout << "substr:" << s << endl;
}
vector 动态拓展,单端数组,一段连续的内存空间,访问数据快
//vector测试
void test04()
{
vector v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
cout << "大小:" << v.size() << endl;
cout << "容量大小:" << v.capacity() << endl;
printsVector(v);
//重置大小,小于原始数据大小则删除之后数据,大于原始大小新的位置赋默认值
v.resize(5);
// 指定位置插入一个数
v.insert(v.begin(), 1000);
// 指定位置删除一个数
v.erase(v.begin());
// 获取元素
v.at(2);
//获取第一个和最后一个元素
v.front();
v.back();
// 预留空间,减少动态扩容次数
v.reserve(100);
}
swap收缩内存空间:vector(v).swap(v);// 匿名对象内存回收
双端数组,增删快,访问不如vector
deque没有容量的概念
栈,先进后出,不允许有便利行为
队列,先进先出,不允许便利,只允许访问队头和队尾数据
class MyCompare
{
public:
bool operator()(const int &v1,const int &v2) const
{
return v1 > v2;
}
};
// 测试map
void test07()
{
map m;
m.insert(pair(1, 50));
m.insert(make_pair(2, 20));
m.insert(map::value_type(3, 30));
//m.insert(map::value_type(3, 35));//无效
cout << "key为3的:"<
https://blog.csdn.net/iicy266/article/details/11906189
class MyCompare
{
public:
bool operator()(const int &v1,const int &v2) const
{
return v1 > v2;
}
};
算数仿函数:加,减,乘,除,取模,取反
关系仿函数:大于、小于…
逻辑仿函数:或与非
主要由头文件algorithem,functional,numeric组成;
// 遍历
for_each(m_L2.begin(), m_L2.end(), print);
// 拷贝并转换
class Transform
{
public:
int operator()(int &a)
{
return a + 10;
}
};
transform(m_L1.begin(), m_L1.end(), m_L2.begin(), Transform());
// 测试 查找算法
// 查找自定义类型 需要重载operator==
void test10()
{
list l;
for (int i = 0; i < 10; i++)
{
l.push_back(i);
}
list::iterator it = find(l.begin(), l.end(), 20);
string str = it == l.end() ? "没找到!" : "找到了!";
cout << str << endl;
}
// accumulate计算自定义数据类型
class MyAccumlate
{
public:
MyAccumlate(){}
MyAccumlate(int age)
{
this->age = age;
}
int age;
int operator()(int t1, const MyAccumlate& t2)
{
return (t1 + t2.age);
}
};
// 测试accumlate 自定义数据类型
void test11()
{
list m_List;
for (int i = 0; i < 20; i++)
{
m_List.push_back(MyAccumlate(i));
}
int result = accumulate(m_List.begin(), m_List.end(), 0, MyAccumlate());
cout << result << endl;
}
#include
using namespace std;
#include
#include
int m_Count = 20;
mutex m;
void thread1()
{
while (m_Count > 0)
{
//mutex 容易死锁
//m.lock();
//lock_guard 能够自解锁,当生命周期结束时,它会自动析构,不影响其他线程
lock_guard lockGuard(m);
if (m_Count > 0)
{
--m_Count;
cout << m_Count << endl;
}
//m.unlock();
}
}
void thread2()
{
while (m_Count > 0)
{
//m.lock();
lock_guard lockGuard(m);
if (m_Count > 0)
{
--m_Count;
cout << m_Count << endl;
}
//m.unlock();
}
}
// 测试线程加锁
void test07()
{
cout << "threaId:" << this_thread::get_id() << endl;
thread th1(thread1);
thread th2(thread2);
//th1.join(); //同步执行
th1.detach(); //异步执行
}
使用了detach()后的问题:
mutex
lock_guard
unique_lock
https://blog.csdn.net/guotianqing/article/details/104002449
async创建后台任务并返回值
future f = async(func);
深入浅出 c++11 std::async
async与Thread的区别
packaged_task
// 测试package_task
void test12()
{
cout << "主线程:" << this_thread::get_id() << endl;
packaged_task mypt([](int inMemb)
{
cout << "执行线程:"<
future
future.wait_for()
查询状态;c++11并发与多线程视频课程
https://www.cnblogs.com/lzpong/p/6397997.html
// TODO
// 使用局部静态变量实现懒汉式单例
// 比较推荐的一种写法,不用使用共享指针
class SingTone
{
private:
SingTone() { cout << "Cteate Class!" << endl; }
~SingTone() { cout << "Delete Class!" << endl; }
public:
static SingTone& getInstance()
{
static SingTone instance;
return instance;
}
};
单例的模板
template
class SingleToneTmp
{
protected:
SingleToneTmp() { cout << "Cteate Class!" << endl; }
~SingleToneTmp() { cout << "Delete Class!" << endl; }
public:
static T& getInstance()
{
static T instance;
return instance;
}
};
class StudSingle :public SingleToneTmp
{
};
简单工厂
enum class CarType { BUICK, CHEVY, CADILIC };
class Car {
public:
virtual void createdCar(void) = 0;
};
...
class Cadilic : public Car
{
public:
virtual void createdCar(void)
{
cout << "Create Cadilic!" << endl;
}
};
...
class CarFactory {
public :
Car* createCarBuyType(CarType type)
{
switch (type)
{
case CarType::BUICK:
return new Buick;
case CarType::CHEVY:
return new Chevy;
case CarType::CADILIC:
return new Cadilic;
default:
break;
}
}
};
抽象工厂
class Factory
{
public :
virtual Car* createCar() = 0;
};
class CadilacFactory :public Factory
{
public:
virtual Car* createCar()
{
cout << "造了一台cadilac" << endl;
return new Cadilic;
}
};
...
shared_ptr f_Sp(new CadilacFactory());
f_Sp.get()->createCar();
class Phone
{
public:
virtual void placeCall() = 0;
virtual void muteCall() = 0;
};
class Huawei :public Phone
{
public :
Huawei() {}
virtual void placeCall() {
cout << "用huawei 打电话!" << endl;
}
virtual void muteCall() {
cout << "用huawei 静音电话!" << endl;
}
~Huawei() { cout << "Huawei析构" << endl; }
};
class Oppop :public Phone
{
public:
Oppop() {}
virtual void placeCall() {
cout << "用Oppop 打电话!" << endl;
}
virtual void muteCall() {
cout << "用Oppop 静音电话!" << endl;
}
~Oppop(){cout << "Oppop析构" << endl;}
};
class Human
{
public :
Human(Phone* p)
{
m_Phone = p;
}
void mackCall()
{
if (m_Phone != nullptr)
{
m_Phone ->placeCall();
}
}
~Human() {cout << "huamn析构" << endl;}
private :
Phone* m_Phone;
};
···
shared_ptr m_huaweiSp(new Huawei());
shared_ptr m_oppoSp(new Oppop());
shared_ptr m_hSp1(new Human(m_huaweiSp.get()));
shared_ptr m_hSp2(new Human(m_oppoSp.get()));
m_hSp1.get()->mackCall();
m_hSp2.get()->mackCall();
c++设计模式之建造者模式
参考:C++11常用新特性快速一览
旧版本中NULL兼容性问题
void Func(char *);
void Func(int);
...
// 下面代码调用的是Func(int),但NULL作为一个void* 指针应该调用第一个函数
Func(NULL);
https://www.cnblogs.com/developing/articles/10890886.html
表示自动推导
int x = 10;
auto *a = &x; //auto被推导为int
auto b = &x; //auto被推导为int*
auto &c = x; //auto被推导为int
auto d = c; //auto被推导为int
const auto e = x; //auto被推导为int
auto f = e; //auto被推导为int
const auto& g = x; //auto被推导为int
auto& h = g; //auto被推导为int
//int i = 10;
//h = i;//error,因为 h为const int& h
使用限制
使用场景:
//旧特性中获取迭代器
vector::iterator it = MyVector.begin();
//新特性中获取迭代器
auto MyIt = MyVector.begin();
从表达式的类型推断出要定义的变量类型,但不初始化变量
int x = 1;
int y = 2;
decltype(x + y) z;// 推到出z是int类型
//旧版本中for循环
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//新版本
for (auto& i : v)
{
cout << i << " ";
}
可直接使用{}完成初始化,如下示例
struct Student
{
int m_Age;
string m_Name;
};
// 测试初始化列表
void test05()
{
Student s1 = { 1,"picher1" };
Student s2 = { 2,"picher2" };
cout << s1.m_Age << s1.m_Name << endl;
}
class Base {
public:
int value1;
int value2;
Base() {
value1 = 1;
}
Base(int value) : Base() { // 委托 Base() 构造函数
value2 = 2;
}
};
int a { 10 };
int arr2[] {1,2,3,4,5};
vector v{ 1,2,3,4 };
Student s{10,"picher"};
for (auto i : v) cout << i << endl;
IBM Developer-轻松编写C++ 单元测试
功能 | VC | AS |
---|---|---|
代码补全 | TAB | ALT + / |
参数提示 | CTRL + SHIFT + 空格 | CTRL + P |
多行注释/反注释 | CTRL + K + C/CTRL + K + U | CTRL+/ |
代码格式化 | CTRL + K + F | CTRL + ALT + L |
转小写 | CTRL + U | CTRL + U |
转大写 | CTRL + SHIFT + U | CTRL + U |
转到行 | CTRL + G | CTRL + G |
重命名 | CTRL + R + R | SHIFT + F6 |
删除一行 | CTRL + SHIFT +L | CTRL + Y |
复制一行 | CTRL + D | CTRL + D |
移动行 | ALT + ↑/↓ | CTRL + ALT + ↑/↓ |
总体来看,都是面向对象语言,思想基本一致。基础数据类型,类的特性,设计模式,容器用法也类似集合。
不同点在:指针,引用,函数定义方式,传参方式,类的继承方式,析构,对泛型的使用方式(C++是模板),还有语言的特殊写法