API语法查询:
https://www.apiref.com/cpp-zh/cpp/language/destructor.html
1,virtual 的使用,虚函数,带有虚函数的类是抽象类,抽象类被继承,体现多态。
2,inline 内联函数 ,编译阶段直接编译到程序中,如果多个文件引用,需要把inline函数加到.h中
3,static 静态成员函数不能使虚函数,因为它不受限于某个对象。
4,c++ C11标准类默认4个特殊成员函数(构造函数,析构函数,拷贝构造函数,拷贝赋值构造运算符operate=)的控制,= default; 和 = delete;
https://www.cnblogs.com/lsgxeva/p/7787438.html/ "=default"函数既可以在类体里(inline)定义,也可以在类体外(out-of-line)定义。class X2{
public: X2() = default; //Inline defaulted 默认构造函数 X2(const X&); // 拷贝构造函数 X2& operator = (const X&); // 拷贝赋值操作符 // X2 A = B;报错 ~X2() = default; //Inline defaulted 析构函数 }; X2::X2(const X&) = default; //Out-of-line defaulted 拷贝构造函数 X2& X2::operator= (const X2&) = default; //Out-of-line defaulted 拷贝赋值操作符 // 为了能够让程序员显式的禁用某个函数,C++11 标准引入了一个新特性:"=delete"函数。程序员只需在函数声明后上“=delete;”,就可将该函数禁用。 class X3 { public: X3(); X3(const X3&) = delete; // 声明拷贝构造函数为 deleted 函数 ,调用这样的操作就会报错 X3& operator = (const X3 &) = delete; // 声明拷贝赋值操作符为 deleted 函数 void *operator new(size_t) = delete; // X3* A = new X3; 会报错 void *operator new[](size_t) = delete; // X3* B = new X3[10]; 会报错 X3* B = new[4] X3; };
5,虚函数 - 抽象类(含有虚函数)-不能实例化,只能被继承类实现 class interfaceClass { public: virtual int processData() = 0; // 0 就是null,就是该虚函数的地址为0,不需要实现。 virtual void getparam() const = 0 ; // const 表示该函数只能被常量对象(const class A object;)访问 ,而且该函数不能改变函数体内的变量。 } 4.6,运算符重载,就是符号变成了函数名 5 C++四种初始化方式:推荐初始化列表方式 classA A: valA(A),valB(B){}; https://www.cnblogs.com/tengzijian/p/17964231
std::string s1="hello"; // (1) 拷贝初始化
std::string s2={"hello"}; // (2) 拷贝初始化
std::string s3{"hello"}; // (3) 直接初始化, 推荐方式
std::string s4("hello"); // (4) 直接初始化
6,C++的“::”运算符
"::"
在C++中表示作用域,和所属关系。 "::"
是运算符中等级最高的,它分为三种,分别如下:
- ps ::在最开头就是全局
::在最开头开始,表示顶层命名空间(全局变量) 等同 std::string <==> ::std::string
一、作用域符号: A::member就表示类A中的成员member。
二、全局作用域符号: :当全局变量在局部函数中与其中某个变量重名,那么就可以用 :: 来区分,如 ::val和val可以同时使用。
三、作用域分解运算符: f()在.h声明,但是在类外定义f时(.c定义时),就要写成voidA::f()
7,C++ struct用法
C++里的struct 类似class: https://www.cnblogs.com/banluxinshou/p/11823158.html
struct Ust {
bool Enable;
int Idx;
Ust ()
{
Enable=false;
Idx=-1;
}
bool fun() {return Idx >= 0;}
};
8,C++析构函数的自动调用问题
首先要明确一点,系统只会自动释放栈内空间,而堆内空间需要用户自己维护。C++中,除了new来的空间存放在堆内,其他均存放在栈中。当单纯的创建对象的时候,对象存放在栈中,此时在程序块的}后面,系统会自动调用析构函数,释放掉栈空间。但是,如果创建了指向new来的一块空间的指针的时候,如果在没有显示释放掉new到的堆空间时,系统是不会自动调用析构函数去释放栈空间中的指针的。
9, 转换问题
static_cast 有继承关系就可以
dynamic_cast .dynamic转换的类需要加一个虚函数。任意一个虚函数都可以
reinterpret_cast 最牛强转,任意类转换
const_cast 一般用于强制消除对象的常量性
10,模板类(实现和声明都放到.h),类模板
类似 #define typename A;#define class B;编译时代入: typename和class一样的,可以互换,就是为了实现多类型
template<typename A, class B, int C, int D>
Class myTemplateClass {
public:
myTemplateClass(): width(C), length(D) { };
~myTemplateClass();
bool big(A a ,B b) {
return a > b?a:b ;
};
int sum(int ,int) {
return C+D;
};
private:
int width;
int length;
};
模板类 ;
int a = 1,b = 2,c = 3,d =4;
myTemplateClass<a,b,c,d> myClass; // 模板类声明时必须显示类模板形参。
myTemplateClass<gettype(a) a,gettype(b) b,c,d> myClass;// 可以这么理解
11. final 关键字,出现在类和成员函数后面,表示该类或成员函数 不允许被继承,只能被使用。
12,override 字段,derived 类 继承基类virtual函数时 使用overrid 字段explicit 显示的表明覆盖base class的function,可以读代码更明确,而且编译器还帮忙检查是否正常的override了。
13,把类就理解成一个大的结构体,里面包含了数据和函数,做到了封装的内聚。
#include <iostream>
#include <string>
#include <vector> // 头文件要加的
int main()
{
using namespace std;
vector<string> myname{"zjq","qjz"}; // 类看着更像结构体了,可以通过 = (), {} new 等做初始化,而使用{}更像时结构体赋值。
for (const auto &name: myname) // C++11 引入了范围基于的 for 循环,使得遍历 std::vector 更简单,告别迭代器 iterator
{
cout<<name<<endl;
}
}
14,xml的解析方法
<path name="speaker">
<ctl name="INT0_MI2S_RX Channels" value="One" />
<ctl name="RX3 MIX1 INP1" value="RX1" />
<ctl name="Speaker Boost" value="ENABLE" />
<ctl name="SPK" value="Switch" />
</path>
#include <iostream>
#include "tinyxml2.h"
using namespace tinyxml2;
int main() {
XMLDocument doc;
// 加载 XML 文件
if (doc.LoadFile("example.xml") != XML_SUCCESS) {
std::cerr << "无法加载文件: " << doc.ErrorIDToName(doc.ErrorID()) << std::endl;
return -1;
}
// 获取根元素
XMLElement* path = doc.FirstChildElement("path");
if (path == nullptr) {
std::cerr << "没有找到根元素" << std::endl;
return -1;
}
// 遍历每一个 ctl 元素
for (XMLElement* ctl = path->FirstChildElement("ctl"); ctl != nullptr; ctl = ctl->NextSiblingElement("ctl")) {
const char* name = ctl->Attribute("name");
const char* value = ctl->Attribute("value");
std::cout << "名称: " << (name ? name : "未知")
<< ", 值: " << (value ? value : "未知") << std::endl;
}
return 0;
}
15,placement new 在分配好的内存空间里 创建对象,比如用来创建内存池。
探秘C++中的Placement New:深度解析与常规new的对比_c++ placement new-优快云博客
16,尽量使用const auto & 引用,避免拷贝内存,造成内存和性能的不足,for /if /switch里可以进行初始化。
比如for(T t = T(10); auto const &t:t) {
}
17,C语言里的 # 和 ##
#define A(x) T_##x ===》链接符
#define B(x) #@x ===》转成字符
#define C(x) #x ==》转换成字串
我们假设:x=1,则有:
A(1)------〉T_1
B(1)------〉'1'
C(1)------〉"1"
18 , [this]
lambda 表达式 去掉冗余的this. this->,让代码更clear。
[this]
是一个捕获列表(capture list),用于在 C++ 中的 lambda 表达式中捕获外部作用域中的变量。在下面这个例子中, [this]
捕获了当前类的指针( this
),使得在 lambda 表达式内部可以访问当前对象的成员变量和成员函数。 具体来说,代码片段的意思是定义一个 lambda 表达式,该表达式接受一个 AudioPort
类型的参数 port
和一个 AudioPortConfig*
类型的参数 config
,并且可以访问当前类的成员。这样可以在 lambda 内部使用当前对象的属性或方法。
ndk::ScopedAStatus ModuleRemoteSubmix::setAudioPortConfig(const AudioPortConfig& in_requested, AudioPortConfig* out_suggested, bool* _aidl_return) {
auto fillConfig = [this](const AudioPort& port, AudioPortConfig* config) {
if (port.ext.getTag() == AudioPortExt::device) {
if (auto pipeConfig = getRemoteEndConfig(port); pipeConfig.has_value()) {
LOG(DEBUG) << "setAudioPortConfig: suggesting port config from the remote end.";
config->format = pipeConfig->format;
config->channelMask = pipeConfig->channelLayout;
config->sampleRate = Int{.value = pipeConfig->sampleRate};
config->flags = port.flags;
config->ext = port.ext;
return true;
}
}
return generateDefaultPortConfig(port, config);
};
return Module::setAudioPortConfigImpl(in_requested, fillConfig, out_suggested, _aidl_return);
}