C++学习10——父类子类的关系

本文介绍了一个C++程序示例,展示了类继承和成员函数重载的概念。通过Employee和Manager两个类的定义及使用,解释了如何在子类中重载和隐藏基类的方法。

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

//std::string类的全名,由于没有加using namespace std;所以要写全名
class Employee{
public:
    Employee(const std::string& name,const std::string& ssn);
    const std::string& get_name() const;
    void print(std::ostream& out) const;
    void print(std::ostream& out,const std::string& msg) const;
protected:
    std::string m_name;
    std::string m_ssn;
};
Employee::Employee(const string& name,const string& ssn):m_name(name),m_ssn(ssn){
    //构造函数
}
inline const std::string& Employee::get_name() const{
    return m_name;
}
inline void Employee::print(std::ostream& out) const{
    out<<m_name<<endl;
    out<<m_ssn<<endl;
}
inline void Employee::print(std::ostream& out,const std::string& msg) const{
    out<<msg<<endl;
    print(out);//调用上一个print()函数,避免代码复制,尽量使用已有的代码写新的代码
}
//print()函数重载
class Manager:public Employee{
public:
    Manager(const std::string& name,const std::string& ssn,const std::string& title);
    const std::string title_name() const;
    const std::string& get_title() const;
    void print(std::ostream& out) const;
private:
    std::string m_title;
};
Manager::Manager(const string& name,const string& ssn,const string& title=""):Employee(name,ssn),m_title(title){   
}
inline void Manager::print(std::ostream& out) const{
    Employee::print(out);
    out<<m_title<<endl;
}
inline const std::string& Manager::get_title() const{
    return m_title;
}
inline const std::string Manager::title_name() const{
    return string(m_title+": "+m_name);
}
int main(){
    Employee bob("Bob Jones","555-44-0000");
    Manager bill("Bill Smith","666-55-1234","Important Person");
    string name=bill.get_name();//okay Manager inherits Employee
    //string title=bob.get_title();//Error--bob is an Employee!
    cout<<bill.title_name()<<'\n'<<endl;
    bill.print(cout);
    bob.print(cout);
    bob.print(cout,"Employee:");
    //bill.print(cout,"Employee:");//error hidden!
}
#include<iostream>
using namespace std;
class A{
public:
    A(ii):i(ii){cout<<"A::A()"<<endl;}
    ~A(){cout<<"A::A()"<<endl;}
    void print(){cout<<"A::print()"<<i<<endl;}
    void print(int i){cout<<i;print();}
    void set(int ii){i=ii;}
private:
    int i;
};
class B:public A{
public:
    B():A(15){
        cout<<"B::B()"<<endl;       
    }//父类的构造函数调用必须在initialize中,通过initialize给父类送参数,如果不传参数给父类,父类会调用默认构造函数。如果没有这句构造函数,会报错。初始化的顺序:声明的顺序,而非写在initialize中的顺序(父类首先被构造,之后成员变量按照写在列表里的顺序构造初始化)
    ~B(){cout<<"B::~B()"<<endl;}
    //析构的顺序与构造相反
    void print(){cout<<"B::print()"<<endl;}
    void f(){
        set(20);
        print();
    }
};
int main()
{
    B b;//B中包含A的所有东西,b初始化时,A的构造函数会被调用
    b.set(10);
    b.print();
    b.f();
    b.print(200);//报错,子类将父类中的函数隐藏
    return 0;
}
//先构造A,再构造B
//先析构B,再析构A
  1. 所有的成员变量都必须在initialize中

  2. 父类的初始化(构造函数调用)必须在initialize中

如果父类中有重载函数,在子类中有与其中之一相同的函数,则父类中的函数隐藏。

子类中print()函数与父类中print()函数无关

### C++子类父类关系及实现方式 #### 父类子类的概念 在C++中,当B类继承A类时,A类被称为基类(父类),而B类则称为派生类(子类)。这种设计允许程序员基于现有的数据类型创建新的数据类型,从而促进代码重用[^1]。 #### 继承的方式及其影响 C++支持多种类型的继承,包括公有(public)、私有(private)以及保护(protected),不同的继承模式决定了派生类如何访问其基类中的成员。通常情况下,默认采用的是私有继承;然而,在面向对象编程实践中,更常见的是使用公有继承来构建父子类间的关系。 #### 对象切片现象 值得注意的是,尽管可以通过父类指针操作子类实例,但直接将子类对象赋值给父类对象会导致所谓的“对象切片”,即只保留属于父类部分的数据成员,丢失掉特化于子类的信息[^2]。 #### 成员覆盖与隐藏 如果子类父类拥有相同名称的方法或属性,则会发生方法覆写或是字段遮蔽的情况。对于静态成员而言,这表现为一种简单的替换行为——子类版本会完全替代父类定义;而对于虚函数来说,则提供了多态性的基础,使得即使通过父类接口也能调用到实际对应的子类功能实现[^3]。 #### 使用示例 下面给出一段简单代码片段展示上述概念的应用: ```cpp #include <iostream> using namespace std; // 定义一个水果类作为基类 class Fruit { public: string name; virtual void showName() const{ cout << "This is a fruit." << endl; } }; // 苹果类继承自Fruit class Apple : public Fruit { private: float weight; // 新增重量属性 public: Apple(float w):weight(w){ this->name="Apple"; } void showWeight()const{ cout<<"The apple weighs "<<this->weight<<endl; } // 覆盖showName() void showName() const override{ cout << "This is an " << this->name << "." << endl; } }; int main(){ Fruit* f=new Apple(0.5); f->showName(); // 输出: This is an Apple. // 体现了动态绑定特性 ((Apple*)f)->showWeight();// 强制转换后可访问特定成员 delete f; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值