Python中的父类和派生类、强制析构

本文通过一个简单的Python程序演示了父类和子类的概念及如何在子类中重载父类的方法。此外,还介绍了Python的内存回收机制以及如何定义析构函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过一个小程序实验了Python中父类和子类的一些性质,直接上代码:

# -*- coding: UTF-8 -*-

class ParentClass:
	def __init__(self):
		self.start()
	def start(self):
		print "parent method"
	def count(self):
		print "1111"
		self.num = 123
		
class ChildClass(ParentClass):
	def __init__(self):
		self.start()
	def start(self):     #重载了父类的方法
		print "child method"
		
def foo():
	obj = ChildClass()  
	obj.count()     #直接调用父类的方法
	print obj.num   #父类中的类变量会被子类全部继承

if __name__ == '__main__':
	foo()

程序输出结果为:

child method
1111
123
Python和java一样都有内存回收机制,不需要调用额外的析构函数进行内存释放。但是当程序中存在无限循环结构时,如果想强行析构,就需要在类中定义__del__方法:

def __del__(self):
    print "object deleted"
当然,析构函数里也可以增加其他函数,比如说我的类里面用了两个进程,某个进程中存在无限循环的结构,就需要在这个函数中把进程终止:

self.process1.terminate()








<think>嗯,用户现在问的是关于C++中父类的虚函数、普通函数以及纯虚函数在子类中的使用情况,以及它们之间的区别。我需要先理清楚每个概念的定义特性,然后对比它们的异同点。 首先,用户的问题有三个部分:1)父类的虚函数普通函数是否都能被子类使用;2)它们的区别;3)纯虚函数的情况。我需要逐一解答,并且确保覆盖到每个部分的细节。 关于第一个问题,虚函数普通函数在子类中的使用。普通函数的话,如果父类中的函数不是虚函数,子类可以继承并使用,但如果子类重写同名函数,会不会有覆盖的问题?这里可能需要解释隐藏(hide)的概念,即如果子类定义了同名函数,不管参数是否相同,父类的同名函数会被隐藏,除非使用using声明引入。而虚函数则不同,通过virtual关键字,子类可以重写,实现多态。 然后是区别,这里需要对比普通函数虚函数在继承中的行为差异。比如,普通函数在编译时确定调用哪个版本,而虚函数在运行时通过虚表动态绑定。此外,虚函数支持多态,而普通函数不支持,子类重写普通函数会导致父类版本被隐藏,除非显式调用。 接下来是纯虚函数,这时候父类变成抽象类,无法实例化,子类必须实现纯虚函数才能被实例化。纯虚函数没有实现,而普通虚函数可以有默认实现。纯虚函数强制子类提供实现,否则子类也会成为抽象类。 用户可能是在学习C++的继承多态,需要明确各个概念的应用场景语法细节。可能存在的误区是认为所有父类函数都可以被子类直接重写,但实际上普通函数的重写会导致隐藏,而虚函数才是真正的重写多态。 另外,用户可能想知道如何选择使用虚函数、普通函数或纯虚函数,因此需要给出使用场景的建议。比如,普通函数适合不需要多态的情况,虚函数用于多态,纯虚函数定义接口。 需要确保回答结清晰,分点说明,可能用示例代码来辅助解释,但根据用户之前的对话,他们可能希望避免代码块过多,但适当举例有助于理解。同时,注意用户之前的系统级指令要求使用中文,行内公式用$...$,独立公式用$$...$$,但这个问题可能不涉及数学公式,所以主要关注代码格式的正确性。 需要检查是否有遗漏点,比如造函数函数是否可以虚函数,但用户的问题可能不涉及这些。重点在于普通函数、虚函数、纯虚函数的区别使用。 最后,总结部分要简明扼要,帮助用户快速回顾要点。确保语言通俗易懂,避免过于技术化的术语,但也要准确无误。</think>在C++面向对象编程中,父类的虚函数、普通函数纯虚函数在子类中的使用规则有显著差异。以下是详细的对比分: --- ### 一、基础概念对比 | **特性** | **普通函数** | **虚函数** | **纯虚函数** | |-------------------|-----------------------|--------------------------|-------------------------| | 定义方式 | 无`virtual`关键字 | `virtual 返回类型 函数名()` | `virtual 返回类型 函数名() = 0` | | 多态支持 | ❌ | ✅ | ✅ (必须实现才能实例化) | | 父类是否可实例化 | ✅ | ✅ | ❌ (成为抽象类) | | 子类必须重写 | ❌ | ❌ | ✅ | --- ### 二、具体行为分 #### 1. **普通函数** - **调用规则**:编译时静态绑定 - **隐藏现象**: ```cpp class Parent { public: void func() { cout << "Parent::func\n"; } // 普通函数 }; class Child : public Parent { public: void func() { cout << "Child::func\n"; } // 隐藏父类版本 }; Child c; c.func(); // 输出 Child::func c.Parent::func();// 输出 Parent::func(需显式调用) ``` - **核心限制**:无法通过基类指针/引用触发子类实现 #### 2. **虚函数** - **调用规则**:运行时动态绑定(通过虚函数表) - **多态实现**: ```cpp class Animal { public: virtual void speak() { cout << "Animal sound\n"; } }; class Dog : public Animal { public: void speak() override { cout << "Woof!\n"; } }; Animal* ptr = new Dog(); ptr->speak(); // 输出 Woof! ✅ ``` - **重要特性**: - 允许通过基类指针调用派生类实现 - 虚函数表(vtable)存储函数地址 - `override`关键字(C++11+)增强安全性 #### 3. **纯虚函数** - **抽象类定义**: ```cpp class Shape { // 抽象类 public: virtual double area() const = 0; // 纯虚函数 }; class Circle : public Shape { public: double area() const override { return 3.14 * radius_ * radius_; } // 必须实现 }; ``` - **强制实现**:未实现纯虚函数的派生类仍是抽象类 - **接口定义**:常用于定义规范(如`virtual ~Interface() = default;`) --- ### 三、关键差异总结 | **对比维度** | 普通函数 | 虚函数 | 纯虚函数 | |-------------------|-----------------------|-------------------------|-------------------------| | 函数绑定时机 | 编译期静态绑定 | 运行期动态绑定 | 运行期动态绑定 | | 多态能力 | 无 | 有 | 有 | | 父类实现必要性 | 必须提供 | 可选(可无实现) | 禁止提供实现(=0语法) | | 内存开销 | 无额外开销 | 虚表指针(通常8字节) | 同虚函数 | | 设计用途 | 通用功能实现 | 扩展点定义 | 接口规范强制 | --- ### 四、进阶应用场景 #### 1. **模板方法模式** ```cpp class GameAI { public: void run() { // 普通函数定义流程 collectResources(); buildStructures(); sendScouts(); } virtual void sendScouts() = 0; // 纯虚函数强制实现 protected: virtual void collectResources() {} // 虚函数提供默认实现 }; ``` #### 2. **函数特殊规则** - 基类函数 **必须为虚函数**: ```cpp class Base { public: virtual ~Base() = default; // 虚函数 ✅ }; class Derived : public Base { public: ~Derived() override { /* 资源释放 */ } }; Base* ptr = new Derived(); delete ptr; // 正确调用Derived函数 ``` #### 3. **协变返回类型(Covariant Return)** ```cpp class Base { public: virtual Base* clone() const { return new Base(*this); } }; class Derived : public Base { public: Derived* clone() const override { // 返回派生类型 ✅ return new Derived(*this); } }; ``` --- ### 五、最佳实践建议 1. **虚函数使用原则**: - 当需要多态行为时使用虚函数 - 基类函数必须为虚函数 - 优先使用`override`关键字(C++11+) 2. **纯虚函数注意事项**: ```cpp class Interface { public: virtual void func() = 0; virtual ~Interface() = default; // 接口类必须虚 }; // 错误示例:未实现纯虚函数 class BadImpl : public Interface {}; // ❌ 仍是抽象类 ``` 3. **性能优化技巧**: - 对性能关键路径慎用虚函数(虚函数调用比普通函数多一次指针跳转) - 使用`final`关键字禁止进一步重写(C++11+): ```cpp class Leaf : public Base { public: void func() final; // 禁止派生类重写 }; ``` --- ### 六、代码验证示例 ```cpp #include <iostream> using namespace std; class Base { public: void normalFunc() { cout << "Base normal\n"; } virtual void virtualFunc() { cout << "Base virtual\n"; } virtual void pureVirtual() = 0; }; class Derived : public Base { public: void normalFunc() { cout << "Derived normal\n"; } void virtualFunc() override { cout << "Derived virtual\n"; } void pureVirtual() override { cout << "Implemented pure virtual\n"; } }; int main() { Derived d; Base* pb = &d; pb->normalFunc(); // 输出 Base normal(静态绑定) pb->virtualFunc(); // 输出 Derived virtual(动态绑定) pb->pureVirtual(); // 输出 Implemented pure virtual d.normalFunc(); // 输出 Derived normal return 0; } ``` --- ### 七、与其他语言对比 | 特性 | C++ | Java | Python | |--------------------|------------------------|-----------------------|-----------------------| | 普通函数重写 | 隐藏父类版本 | @Override注解强制检查 | 直接覆盖 | | 虚函数关键字 | `virtual` | 默认所有方法虚函数 | 所有方法默认"虚" | | 纯虚函数语法 | `= 0` | `abstract`关键字 | 抛出`NotImplementedError` | | 接口定义 | 通过纯虚类实现 | `interface`关键字 | 通过抽象基类(ABC) | --- 理解这三类函数的区别,是掌握C++多态机制的核心。实际开发中应根据需求选择: - **普通函数**:用于不需要多态的固定实现 - **虚函数**:建可扩展的类层次结 - **纯虚函数**:定义强制接口规范
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值