C++ 类继承:基类与派生类的概念和实践
下面先定义一个普通类 Person,包含姓名与状态信息。
// Person.h
#ifndef PERSON_H
#define PERSON_H
#include <string>
class Person
{
private:
std::string m_first;
std::string m_last;
bool m_active;
public:
Person(const std::string& f = "none",
const std::string& l = "none",
bool a = false);
void show() const;
bool isActive() const { return m_active; }
void setActive(bool v) { m_active = v; }
};
#endif
// Person.cpp
#include <iostream>
#include "Person.h"
Person::Person(const std::string& f,
const std::string& l,
bool a)
: m_first(f), m_last(l), m_active(a) {}
void Person::show() const
{
std::cout << m_last << ", " << m_first;
}
// main.cpp
#include <iostream>
#include "Person.h"
int main()
{
Person p1("Chuck", "Blizzard", true);
Person p2("Tara", "Boomdea", false);
p1.show();
std::cout << (p1.isActive() ? ": 已激活" : ": 未激活") << '\n';
p2.show();
std::cout << (p2.isActive() ? ": 已激活" : ": 未激活") << '\n';
return 0;
}
继承关系
从一个已有的类派生出新类时,原来的类称为基类,新生成的类称为派生类。下面以 Player 为基类,RankedPlayer 为派生类说明。
访问控制
public成员:任意地方都可以访问。protected成员:只能在类本身及其派生类中访问。private成员:只能在当前类内部访问,派生类不能直接访问。
公有继承示例
// Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <string>
class Player
{
private:
std::string m_first;
std::string m_last;
bool m_hasTable;
public:
Player(const std::string& f = "none",
const std::string& l = "none",
bool t = false);
void display() const;
bool hasTable() const { return m_hasTable; }
void setTable(bool v) { m_hasTable = v; }
};
class RankedPlayer : public Player
{
private:
unsigned int m_score;
public:
RankedPlayer(unsigned int s = 0,
const std::string& f = "none",
const std::string& l = "none",
bool t = false);
RankedPlayer(unsigned int s, const Player& p);
unsigned int score() const { return m_score; }
void setScore(unsigned int s) { m_score = s; }
};
#endif
// Player.cpp
#include <iostream>
#include "Player.h"
Player::Player(const std::string& f,
const std::string& l,
bool t)
: m_first(f), m_last(l), m_hasTable(t) {}
void Player::display() const
{
std::cout << m_last << ", " << m_first;
}
RankedPlayer::RankedPlayer(unsigned int s,
const std::string& f,
const std::string& l,
bool t)
: Player(f, l, t), m_score(s) {}
RankedPlayer::RankedPlayer(unsigned int s, const Player& p)
: Player(p), m_score(s) {}
// main.cpp
#include <iostream>
#include "Player.h"
int main()
{
Player p("Tara", "Boomdea", false);
RankedPlayer rp(1212, p);
std::cout << "姓名:";
rp.display();
std::cout << "\n是否有桌:" << (rp.hasTable() ? "是" : "否")
<< "\n积分:" << rp.score() << '\n';
return 0;
}
派生类构造函数
派生类对象的构造顺序是:先调用基类构造函数,再执行派生类构造。若不在成员初始化列表中显式调用基类构造函数,编译器会尝试调用基类的默认构造函数。因此,除非想使用默认构造,否则应在初始化列表中显式指定。
// 显式调用基类构造函数
RankedPlayer::RankedPlayer(unsigned int s,
const std::string& f,
const std::string& l,
bool t)
: Player(f, l, t), m_score(s) {}
下面的写法则会先调用 Player() 默认构造,再用参数构造基类部分的效果将丢失,通常不是期望行为。
// 不推荐:基类部分使用默认构造
RankedPlayer::RankedPlayer(unsigned int s,
const std::string& f,
const std::string& l,
bool t)
{
m_score = s;
}
继承方式
C++ 支持三种继承方式,最常见的是 public 继承:
- public 继承:基类的 public 成员在派生类中仍是 public,protected 成员仍是 protected。
- protected 继承:基类的 public 和 protected 成员在派生类中变为 protected。
- private 继承:基类的 public 和 protected 成员在派生类中变为 private;class 默认继承方式为 private。
派生类虽然包含了基类的私有成员,但无法直接访问它们,必须通过基类提供的 public 或 protected 接口操作。
]]>