16. 子类父类关系

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,好处是子类可以直接调用m_name,m_ssn.
  //                    坏处是不知道子类会拿m_name和m_ssn做什么.
  //建议成员变量用private.
  protected: 
    std::string m_name;
    std::string m_ssn;
};

//构造函数
Employee::Employee(const string& name, const string& ssn):m_name(name),m_ssn(ssn)
{
   //initializer list sets up the values.
}

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 //两个print函数名相同,参数不同,函数重载
{
  out << msg << endl;
  print(out); // 编译器会根据参数的数量类型不同,决定该调用哪一个函数. 
             //调用了第一个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)
{
  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");
   //父类Employee,此时Employee中的bob对象的protected成员变量m_name = "Bob Jones", m_ssn = "555-44-0000" (成员变量是对象的,成员函数是类的)

  Manager bill("Bill Smith", "666-55-1234", "Important Person"); 
  //子类Manager的对象bill中的私有成员变量m_title = "Important Person", 同时m_name = "Bill Smith", m_ssn = "555-44-0000".

  string name = bill.get_name(); 
//子类调用父类的成员函数,name = "Bill Smith".

  //string title = bob.get_title(); //此行出错,不能如此调用,父类不能调用子类的东西.

  cout << bill.title_name() << '\n' << endl;
   // "Important Person : Bill Smith

  bill.print(cout); //"Bob Jones" "555-44-0000"
                    //"Important Person.

  bob.print(cout); //"Bob Jones" "555-44-0000"

  bob.print(cout, "Employee:"); //Employee: "Bob Jones" "555-44-0000"

  //bill.print(cout, "Employee:"); //此行出错

  return 0;
}
#include 
using namespace std;

class A
{
  public:
    A(int ii):i(ii) 
    {
       cout << "A::A()" << endl;
    }
    `A()
    {
       cout << "A::`A()" << endl;
    }
    void print()
    {
       cout << "A::f()" << endl;
    }
    void set(int ii)
    {
      i = ii;
    }
 private:
    int i;
};

class B:public A
{
  public:
    B():A(15) {} //B的构造函数
    void f()
    {
      set(20);
      print();
    }
};

int main()
{
  B b; //程序报错,原因B b,需要调用父类A的无参数构造函数. A类中没有.
       //初始化子类,而父类是子类的一部分,则父类也需要初始化. 子类不懂父类是初始化的,所以需要交给父类自己初始化. 而此时A没有给出缺省构造函数,所以需要告诉如何调用A的构造函数. 
      //解决方法:添加B的构造函数 B():A(15) 则首先对A(15)初始化,然后调用A的构造函数,然后调用B的构造函数 (初始化列表)       
  b.set(10);
  b.print();
  b.f();
  return 0;
}

初始化列表的顺序

c++
class father
{
public:
father(int x, float y) { }
private:
int x;
float y;
};
class son: public father
{
public:
son:father(10, 10.0, 5);//按照声明的顺序, 父类最先,子类列表的顺序初始化. x=10, y = 10.0, m = 5.
private:
int m;
};
//析构的时候,先把子类清理,再清理父类的.

注意:如果没有经过初始化列表的方式,传送参数给父类的话,将会调用父类的无参数构造函数.

只要C++这么做的:
当父类中有成员函数print(), print(int i)
子类中也有成员函数print()
此时子类B b, b.print() 此时父类的成员函数print()和print(int i)都隐藏了.

你可能感兴趣的:(C++)