典型的使用继承的程序

网上找到的,转帖学习一下。

#!/usr/bin/python
# Filename: inherit.py

class SchoolMember:
    '''Represents any school member.'''
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print '(Initialized SchoolMember: %s)' % self.name

    def tell(self):
        '''Tell my details.'''
        print 'Name:"%s" Age:"%s"' % (self.name, self.age),

class Teacher(SchoolMember):
    '''Represents a teacher.'''
    def __init__(self, name, age, salary):
        SchoolMember.__init__(self, name, age)
        self.salary = salary
        print '(Initialized Teacher: %s)' % self.name

    def tell(self):
        SchoolMember.tell(self)
        print 'Salary: "%d"' % self.salary

class Student(SchoolMember):
    '''Represents a student.'''
    def __init__(self, name, age, marks):
        SchoolMember.__init__(self, name, age)
        self.marks = marks
        print '(Initialized Student: %s)' % self.name

    def tell(self):
        SchoolMember.tell(self)
        print 'Marks: "%d"' % self.marks

t = Teacher('Mrs. Shrividya', 40, 30000)
s = Student('Swaroop', 22, 75)

print # prints a blank line

members = [t, s]
for member in members:
    member.tell() # works for both Teachers and Students

子类的初始化方法里已经调用过基类的__init__方法,为self.name和self.age赋值,所以子类的tell方法调用基类的tell方法时,self.name和self.age已经被赋值。





<think>嗯,用户这次的问题集中在编译器处理类继承的机制上。用户提到一个关于C++类成员解析的参考引用,但实际需求更偏向继承原理。从上下文看,用户应该是正在学习C++的编译原理,特别是面向对象特性在底层的实现方式。用户的上个问题涉及类作用域查找,这次转向继承机制,说明在系统性地探索C++对象模型。这类问题通常出现在开发复杂类层次或调试内存布局时。用户可能遇到多重继承的歧义问题,或是想了解虚函数调用的开销来源。编译器处理继承的核心在于内存布局和名称解析。需要分三块解释:首先是单继承下子类如何包含父类成员并保持偏移量,这里要强调基类子对象的概念;其次是多重继承带来的地址调整问题,特别是菱形继承的虚基类优化;最后要说明虚函数表的多级间接访问机制,这是运行时多态的基础。用户没有指定语言深度,但引用提到C++,就按最复杂的编译场景处理。需要补充GCC/Clang的具体实现差异,因为MSVC的虚表结构是不同的。不过用户可能更关注通用原理而非具体编译器,所以重点描述标准要求的行为而非实现细节。注意到用户要求"尽可能参考上次回答",虽然上次讨论的是类作用域而非继承,但查找规则在继承体系中同样适用——名称遮蔽规则和基类搜索顺序是连贯知识。可以延续作用域链的概念,扩展到基类作用域的遍历逻辑。用户引用的[1]提到"避免访问错误变量",这提示实际编码痛点。在继承场景中,典型问题包括:派生类成员遮蔽基类成员时的意外行为,多重继承的同名成员歧义。需要强调编译器的名称修饰(namemangling)规则和using声明解决方案。虚函数部分要特别解释动态绑定的编译期检查:编译器如何验证重写合法性(签名匹配、协变返回类型等),以及为什么非虚函数的调用是静态绑定。这点常被初学者混淆。是否需要解释RTTI的实现?用户没明确问但属于继承机制的衍生内容。考虑到篇幅,放在最后简要说明type_info对象与虚表的关系即可。</think> 好的,编译器处理类继承的原理及实现方式是C++实现多态性的核心机制,主要涉及以下关键方面: 1. **内存布局与对象表示** * **基类子对象:** 当派生类继承基类时,派生类对象的内存布局首先包含基类的完整成员变量副本(基类子对象),然后才是派生类自身定义的成员变量。 * **单继承:** 内存布局相对简单。派生类对象 = 基类子对象 + 派生类自身成员。 * **多重继承:** 派生类对象包含多个基类子对象,这些子对象按继承列表中声明的顺序排列在内存中。每个基类子对象有其独立的内存起始位置(基址偏移量)。 * **虚拟继承:** 用于解决“菱形继承”中的二义性和数据冗余。编译器会为含有虚基类的类生成一个指向虚基类子对象的指针(通常称为 `vbptr`),并确保虚基类子对象在整个继承层次中只存在一个副本。虚基类子对象通常放置在派生类对象内存布局的最末尾。 ```cpp class Base { int base_data; }; class Derived : public Base { int derived_data; }; // Derived对象内存布局: [Base::base_data | Derived::derived_data] ``` 2. **名称查找与作用域** * **成员查找顺序:** 编译器在解析一个成员(变量或函数)名称时,遵循特定的顺序(“名字隐藏”规则):先在当前类作用域(包含当前类及其嵌套类)查找,如果没找到,则依次在直接基类作用域(按照继承声明顺序)中查找,直到找到或查完所有基类(最终可能在全局作用域查找)。这种查找是深度优先、从左到右的。 * **隐藏与重写:** 派生类中定义的成员会**隐藏**基类中同名(即使是不同类型、不同参数)的成员(非虚函数)。要调用被隐藏的基类成员,需要使用作用域解析运算符 `BaseClass::member`。只有 `virtual` 函数才存在**重写**的概念,要求函数签名完全相同(C++11 后可用 `override` 显式声明以确保正确重写)。 * **虚函数表指针 (`vptr`):** 如果一个类声明或继承了至少一个虚函数,编译器会为该类生成一个 **虚函数表 (`vtable`)** 。同时,在**该类(以及后续所有派生类)的每个对象**的内存布局最开头(通常是,但非强制)添加一个隐藏指针成员——**虚函数表指针 (`vptr`)** 。这个 `vptr` 指向该对象所属类的 `vtable`。 3. **虚函数表 (`vtable`)** * **内容:** `vtable` 是一个在编译时创建、程序加载时初始
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值