Joe1sn's Cabin

【置顶】【编程】开发笔记

日常开发遇到的一些坑,记录一下挺有意思的

多态的概念

和继承不同的是,他是根据“动作”的不同进行的分类。

在c中想要有一个数组存放既有int类型又有string类型,类似python中的{123, "AAA", "BBB", 456},但是c数组中只能存在一个类型,所以不可能。

但是我们可以定义一个type类型,intstring是他的子类,由多态的概念,可以创建一个 type* a[0x10]这样的数组,将intstring类型放在里面,其中需要的是父类引用虽然在c++中我们可以直接传入对象的地址到数组中即可

多态允许我们使用统一的接口来操作不同的对象,而具体执行哪个操作,则由对象自身的实际类型来决定。

多态存在的三个必要条件

  1. 继承:必须存在继承关系。
  2. 重写:子类必须对父类的方法进行重写(Override)。
  3. 父类引用指向子类对象:这是实现多态的关键代码形式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 父类:动物
class Animal {
String name;

public Animal(String name) {
this.name = name;
}

public void eat() {
System.out.println(name + "正在吃东西。");
}

public void makeSound() {
System.out.println("动物发出声音。");
}
}

// 子类:狗,继承自动物
class Dog extends Animal { // “Dog is an Animal”
public Dog(String name) {
super(name); // 调用父类构造器
}

// 重写父类方法,以实现特定行为
@Override
public void makeSound() {
System.out.println(name + "汪汪叫!");
}

// 扩展新功能
public void fetch() {
System.out.println(name + "在接飞盘。");
}
}

// 子类:猫,继承自动物
class Cat extends Animal { // “Cat is an Animal”
public Cat(String name) {
super(name);
}

// 重写父类方法
@Override
public void makeSound() {
System.out.println(name + "喵喵叫!");
}
}

public class Test {
public static void main(String[] args) {
// 多态的经典体现:父类引用指向子类对象
Animal myDog = new Dog("旺财"); // Animal 引用指向 Dog 对象
Animal myCat = new Cat("咪咪"); // Animal 引用指向 Cat 对象

// 调用重写的方法
myDog.makeSound(); // 输出:旺财汪汪叫!
myCat.makeSound(); // 输出:咪咪喵喵叫!

// 调用未重写的方法
myDog.eat(); // 输出:旺财正在吃东西。
myCat.eat(); // 输出:咪咪正在吃东西。

// 多态的优势:编写通用代码
Animal[] animals = {new Dog("小黑"), new Cat("小白")};
animalConcert(animals);
}

// 一个通用的方法,接收父类类型参数,可以处理任何子类对象
public static void animalConcert(Animal[] animals) {
for (Animal animal : animals) {
animal.makeSound(); // 这里不需要知道具体是Dog还是Cat,它们会自己“叫”
}
}
}
1
2
3
4
5
6
旺财汪汪叫!
咪咪喵喵叫!
旺财正在吃东西。
咪咪正在吃东西。
小黑汪汪叫!
小白喵喵叫!

power toys键盘映射失效

vscode使用管理员权限运行时使用的是映射之前的输入

普通模式下使用的时映射后的输入

目前还没找大解决方法

python sqlalchemy 查询结果扩大化

1
2
3
def get_self_info(uuid: str):
tasks = session.query(SelfInfo).filter(uuid == uuid).all()
return tasks

很明显的typo错误,uuid == uuid是恒成立的,所以会返回所有的结果,导致某个用户获得全部的结果

应当改为

1
2
3
def get_self_info(need_uuid: str):
tasks = session.query(SelfInfo).filter(SelfInfo.uuid == need_uuid).all()
return tasks

甚至

1
2
3
def get_self_info(uuid: str):
tasks = session.query(SelfInfo).filter(SelfInfo.uuid == uuid).all()
return tasks

c++ Qt6 emit 时undefine

原因是类中没有添加QT的宏定义Q_OBJECT,正常应该如下

1
2
3
4
5
6
7
8
class BeaconTable :public BasicTable<TargetInfo>
{
Q_OBJECT
signals:
void doA(int Id);
void doB(int Id);
};

抽象类中不能使用该宏定义

c++ 抽象类

1
2
3
template<typename T>
class Table :
{}

在cpp中要

1
2
template<typename T>
void Table<T>::deleteRow(int row){}

并且明确具体的抽象类

1
2
template class Table<int>;
template class Table<char*>;

python-asyncio.StreamReader read不完全

比如期待 data=read(n)但是len(data) < n是因为缓冲区大小或者去处理其他的read导致一次await read无法读取完毕,但是可以利用循环分块读取

1
2
3
4
5
while len(data) < file_len:
chunk = await reader.read(file_len - len(data))
if not chunk:
break
data += chunk

python-sqlalchemy偶尔出现 tuple Index out of range

7b835aba816d169237c705380616a11c

model如下

1
2
3
4
5
6
7
class Sessions(Base):
'''Session used in cookie'''
__tablename__ = 'sessions'
id = Column(Integer, primary_key=True, autoincrement=True) # PK
created_at = Column(Integer, default=lambda: int(time.time()), nullable=False)
username = Column(String(32), nullable=False)
token = Column(String(64), nullable=False)

查询controller如下

1
2
3
4
5
6
7
def check_session(stoken: str) -> bool:
from db import session
exists = session.query(
Sessions.id)
.filter(Sessions.token == stoken)
.all()
return len(exists>=1)

可能有其他错误,并且只是偶尔发生

e91dcee379e16cbd36012b44b2fbe4ec

78a83b20272bd1dc0f27f145e34ef970

原因:DBAPI中的并发问题,一个连接不能同时处理大量信息

解决:在这个controller中新建一个连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class ConnDB:
#...
self.__engine = create_engine(
'sqlite:///{}'.format(self.__path),
connect_args={"check_same_thread": False,
"timeout": 30, # 设置超时
"isolation_level": "IMMEDIATE"}, # 更好的并发控制
pool_pre_ping=True,
echo=False)
self.__session = sessionmaker(bind=self.__engine, autocommit=False, autoflush=False,)
#...

Session = conn_db.get_session()

def check_session(stoken: str) -> bool:
db = Session()
exists = db.query(
db.query(Sessions.id)
.filter(Sessions.token == stoken)
.exists()
).scalar()
db.close()
return exists

vscode鼠标拖动代码页分栏失效/没反应

img

环境:windows

解决方法:cmd+shift+p 运行两次 Developer: Toggle Screencast Mode

if-else与++i --i

img

if最好先把else也写上,i++是语句结束后i+1++i是立即加

左值与右值

左值:表达式左边的值,可以被查找到地址的、持久存在的值

右值:字面量,或者std::move后的左值

左值引用:就是变量的别名

image-20250310214208773

右值引用:绑定到临时、即将销毁的对象,使用方法int &&right。意义就是避免内存操作

构造函数

构造函数就是一个类初始化的时候所需要的函数,主要分为以下几类

  • 默认构造函数
  • 带参数的构造函数
  • 拷贝构造函数:可以实现对象的深拷贝和浅拷贝,省略&会导致无限递归
  • 移动构造函数:接受一个右值引用(std::move
  • 转换构造函数
  • 委托构造函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class Base {

public:
int val;

//默认构造函数
Base():val(int(0)) {
std::cout << "默认构造函数. value is " << this->val << std::endl;
}

//带参数的构造函数
Base(int v):val(v) {
std::cout << "带参数的构造函数. value is " << this->val << std::endl;

}

//拷贝构造函数
Base(const Base& other): val(other.val) {
std::cout << "拷贝构造函数. value is " << this->val << std::endl;
}

//移动构造函数
Base(Base&& other) noexcept: val(other.val) {
other.val = 0xFF;
std::cout << "移动构造函数. value is " << this->val << std::endl;
}

//转换构造函数
explicit Base(double v): val(static_cast<int>(v)) {
std::cout << "转换构造函数. value is " << this->val << std::endl;
}

//委托构造函数
Base(char v) : Base() {
this->val = v;
std::cout << "委托构造函数. value is " << this->val << std::endl;

}


~Base() {};
};

int main() {
Base a; //默认
Base b(1); //带参数
Base c(b); //拷贝
Base d(std::move(b)); //移动
Base e(3.124); //转换
Base f('A'); //委托

return 0;
}

image-20250310213435929