c++ 基础 笔记
1?外部访问就是 实例类后 访问类中变量
class MyClass {
public:
int publicVar; // 公有变量
protected:
int protectedVar; // 受保护变量
private:
int privateVar; // 私有变量
};
MyClass obj;
obj.publicVar = 1; // 正确: 公有变量可以在类外部直接访问
obj.protectedVar = 2; // 错误: 受保护变量不能在类外部直接访问
obj.privateVar = 3; // 错误: 私有变量不能在类外部直接访问
2 基类protected成员是子类的内部成员
class Base {
private:
int privateVar; // Base类私有成员
protected:
int protectedVar; // Base类受保护成员
};
class Derived : public Base {
public:
void AccessMembers() {
// privateVar = 1; // 错误: Derived类不能访问Base类的私有成员
protectedVar = 2; // 正确: Derived类可以访问Base类的受保护成员
}
};
int main() {
Derived obj;
// obj.privateVar = 1; // 错误: 不能在类外部访问私有成员
// obj.protectedVar = 2; // 错误: 不能在类外部访问受保护成员
}
3 创建指针 指向对象用 -> ; 实例化对象用 .
3.1 用 -> 的堆 ( -> 不能用在栈上)
ThrLevel1* thrLevel1 = new ThrLevel1(this, ok); // 创建 指针型用 ->
connect(thrLevel1, &ThrLevel1::signal, this, &qt_ok::signalThrLevel1);
// 启动线程
thrLevel1->setInstId("BTC-USDT");
thrLevel1->start();
3.2 用 . 的栈
ThrLevel1 thrLevel1(this, ok);
thrLevel1.setInstId("BTC-USDT"); // 使用点操作符访问对象的成员函数
thrLevel1.start();
4?名称遮蔽? 加类型名称 声明变量 是局部变量 把类全局变量搞成了 变量所在的局部变量
class MyClass {
public:
MyClass() {
MyType* myVar = new MyType(); // 这里创建了一个局部变量 myVar
// ...
}
~MyClass() {
delete myVar; // 这里尝试删除的是成员变量 myVar,但它实际上从未被赋值
}
private:
MyType* myVar; // 这是类的成员变量
};
如果?myVar 定义的是类的成员变量 但是在构造函数中? 加类型名称 声明变量 导致成了局部变量
MyType* myVar = new MyType();
5 取址和引用(别名)要区分
Okex2* p = &ok; // p 是指向 Okex2 类型对象的指针,现在 p 存储了 ok 的地址
Okex2& ref = ok; // ref 是 ok 对象的引用
6 多个类传递使用只声明一次 ok, 传递指针 定义指针型成员 thrLevel1->okInstance = &ok;
// 1 声明
ok()
// 2 设置方法 让别的类可以外部 取到 ok的内存地址 取指
Ok* qt_ok::getOk()
{
return &ok;
}
// 3 别的类要 声明指针变量 之后ok对象的地址赋值给 此变量
// ThrBase.h
#include "Ok.h"
class ThrBase : public QThread {
Q_OBJECT
public:
ThrBase(QObject* parent);
~ThrBase();
void setOkInstance(Ok* ok);
protected: // 与子类共享的内部变量
Ok* okInstance; // 存储Okex2实例的指针
// ThrBase.cpp
#include "ThrBase.h"
ThrBase::ThrBase(QObject* parent) : okInstance(nullptr))
{
}
ThrBase::~ThrBase()
{
}
void ThrBase::setOkInstance(Ok* ok)
{
okInstance = ok;
}
//4 传值
thrLevel1 = new ThrLevel1(this); // 创建 指针型用 ->
thrLevel1->setOkInstance(this->getOk());
不用 get set 封装
ok();
thrLevel1->setOkInstance(&ok);
不用封装 setOkInstance方法 直接赋值
将
okInstance
成员变量改为public
thrLevel1->okInstance = &ok;
7 成员变量?局部变量
private: //?
成员变量
? ? std::string host;
void re(){
? std::string x ; // 局部变量
}
8 类的静态成员(全局成员)和非静态成员
class Car {
public:
int year; // 非静态成员变量
static int numberOfCars; // 静态成员变量
Car() { // 构造函数
numberOfCars++; // 每创建一个Car对象,静态成员变量numberOfCars就增加1
}
};
int Car::numberOfCars = 0; // 初始化静态成员变量
+--------------------------+
| 代码区 |
| 存放CPU执行的机器指令代码 |
+--------------------------+
| 常量存储区 |
| 存放常量字符串和其他常量 |
+--------------------------+
| 全局/静态存储区 (BSS段) |
| 未初始化的全局变量和静态变量 |
+--------------------------+
| 全局/静态存储区 (数据段) |
| 已初始化的全局变量和静态变量 |
+--------------------------+
| 堆区 |
| 通过new分配的内存 |
+--------------------------+
| 栈区 |
| 函数调用时的局部变量和参数 |
+--------------------------+
// 创建对象 就分配在栈区 new就在堆区
基类 ThrBase
+---------------------+
| vptr | ----> 指向 ThrDerived1 的 vtable 纯虚函数表
+---------------------+ (如果 ThrDerived1 中有新的虚函数或覆盖了基类的虚函数,则包含这些函数的指针)
| ... 基类成员 ... |
+---------------------+
派生类 ThrDerived1 的对象内存布局:
+---------------------------------+
| ThrBase 部分 |
+---------------------------------+
| ThrBase 的非静态数据成员 |
+---------------------------------+
| ThrBase 的虚函数表指针(vptr) | ----> 指向 ThrDerived1 的虚函数表
+---------------------------------+
| ThrDerived1 部分 |
+---------------------------------+
| ThrDerived1 的非静态数据成员 |
+---------------------------------+
| ThrDerived1 重写的虚函数 |
+---------------------------------+
| ThrDerived1 特有的虚函数 |
+---------------------------------+
| ThrDerived1 特有的非虚函数 |
+---------------------------------+
9 继承基类后的多态(区别类的多态) 后 使用 基类指针 用基类 有新功能
class Base {
public:
virtual void doSomething() = 0; // 纯虚函数
virtual ~Base() {} // 虚析构函数以确保正确的析构派生类
};
class Derived : public Base {
public:
void doSomething() override { // 必须实现基类的纯虚函数
// ... 实现细节 ...
}
};
// 多态
ThrBase* base1 = new ThrDerived1(); 只能访问基类部分 run已经被改写所以不是纯虚函数
// 继承后的派生类
ThrDerived1* base1 = new ThrDerived1(); 可以访问所有部分
多态性主要指的是能够通过基类的接口(指针或引用)来操作派生类对象,并在运行时根据对象的实际类型调用相应的重写函数。当使用派生类类型的指针时,你直接调用的是那个派生类的成员函数,这是静态绑定。多态性涉及到动态绑定,即在运行时才确定调用哪个具体的函数。
10 python的 @classmethod 与 c++静态static
// .h
class Db {
public:
// ... 其他成员 ...
static bool createTableWithAttrsPlus(Db& db, const std::string& table_name, const std::vector<std::string>& attrs);
// ... 其他成员 ...
};
// .cpp
bool Db::createTableWithAttrsPlus(Db& db, const std::string& table_name, const std::vector<std::string>& attrs) {
// ... 实现创建表的逻辑 ...
}
// 使用
std::vector<std::string> attrs = { /* 属性列表 */ };
bool success = Db::createTableWithAttrsPlus(dbInstance, "table_name", attrs);
静态函数本身不占用调用者的堆栈或堆空间,因为它们属于类,而不是类的某个实例
区别与先实例化或先创建对象指针
// 如果是对象实例
Db db;
db.getDatabaseConnection();
// 如果是对象指针
Db* db = new Db();
db->getDatabaseConnection();
+------------------+
| 代码区 |
| (存放程序的指令) |
+------------------+
| 常量区 |
| (存放常量数据) |
+------------------+
| 全局/静态存储区 |
| (全局变量和静态变量)|
+------------------+
| 堆 |
| (动态分配的内存) |
+------------------+
| 栈 |
| (函数调用和局部变量)|
+------------------+
代码区:存放CPU执行的机器指令。
常量区:存放字符串常量和其他常量数据。这部分内存只读。
全局/静态存储区:存放全局变量和静态变量。在程序(进程)的生命周期内一直存在。
堆:由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。
栈:由操作系统自动分配释放,存放函数的参数值、局部变量等。其操作类似于数据结构中的栈。
11 静态变量?
静态成员变量在类的所有实例之间共享,它们不属于任何单个对象实例,而是属于类本身。在C++中,这意味着无论创建了多少个对象,静态成员变量只有一份拷贝。
任何能够访问该静态成员变量的代码都可以对其进行读写(除非它被声明为
const(只读)
),无论这个代码位于哪个对象中。
#include <iostream>
#include <vector>
class MyClass {
public:
static std::vector<int> shared_data; // 静态成员变量
void addValue(int val) {
shared_data.push_back(val); // 向静态成员变量中添加数据
}
void printValues() {
for (int val : shared_data) {
std::cout << val << " ";
}
std::cout << "\n";
}
};
// 在类外初始化静态成员变量
std::vector<int> MyClass::shared_data;
int main() {
MyClass obj1;
MyClass obj2;
obj1.addValue(1); // obj1 添加值到 shared_data
obj2.addValue(2); // obj2 也添加值到同一个 shared_data
// 两个对象打印出相同的静态成员变量
obj1.printValues(); // 输出: 1 2
obj2.printValues(); // 输出: 1 2
return 0;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!