C++ Primer Plus 第十三章知识点简化
1. 简单的基类
由于面向对象编程主要目的之一就是提供可重写的代码,对于扩展和修改类,除了去源码中修改之外,还有就是类继承;从一个类派生出另一个类时,原始类称为 基类,继承类称为 派生类。简单看下下面的程序:
#ifndef HEAD_H_
#define HEAD_H_
#include<iostream>
#include<string>
using namespace std;
// ============ simple base class ==================
class TableTennisPlayer{
private:
string firstname;
string lastname;
bool hasTable;
public:
TableTennisPlayer(const string& fn = "none", const string& ln = "none", bool ht = false);
void Name() const;
bool HasTable() const { return hasTable; };
void ResetTable(bool v) { hasTable = v; };
};
#endif
#include "head.h"
TableTennisPlayer::TableTennisPlayer(const string& fn, const string& ln,
bool ht) : firstname(fn), lastname(ln), hasTable(ht) {}
//TableTennisPlayer::TableTennisPlayer(const string& fn, const string& ln, bool ht) {
// firstname = fn;
// lastname = ln;
// hasTable = ht;
//}
void TableTennisPlayer::Name() const{
cout << lastname << ", " << firstname;
}
#include <iostream>
#include "head.h"
using namespace std;
int main(void){
TableTennisPlayer player1("Chuck", "Blizzard", true);
TableTennisPlayer player2("Tara", "Boomdea", false);
player1.Name();
if (player1.HasTable())
cout << ": has a table.\n";
else
cout << ": hasn't a table.\n";
player2.Name();
if (player2.HasTable())
cout << ": has a table";
else
cout << ": hasn't a table.\n";
return 0;
}
2. 派生一个类
在基类继承的时候,若是class B : public A
,那么A
是基类且B
是公有派生。此时基类成员和共有派生类成员之间的关系是怎样?尤其是私有成员有哪些需要注意?
公有派生的知识点:
- 基类的公有成员成为派生类的公有成员;
- 基类的私有部分只能通过基类的公有和保护方法访问;
- 基类指针可以不进行显示类型转换的情况下指向派生类对象,基类引用也可以不进行~来引用派生类对象。
#ifndef HEAD_H_
#define HEAD_H_
#include<iostream>
#include<string>
using namespace std;
// ================= simple base class =======================
class TableTennisPlayer{
private:
string firstname;
string lastname;
bool hasTable;
public:
TableTennisPlayer(const string& fn = "none",
const string& ln = "none", bool ht = false);
void Name() const;
bool HasTable() const { return hasTable; };
void ResetTable(bool v) { hasTable = v; };
};
// ================ simple derived class =====================
class RatedPlayer : public TableTennisPlayer{
private:
unsigned int rating;
public:
RatedPlayer(unsigned int r = 0, const string& fn = "none",
const string& ln = "none", bool ht = false);
RatedPlayer(unsigned int r, const TableTennisPlayer& tp);
unsigned int Rating() const { return rating; }
void ResetRating(unsigned int r) { rating = r; }
};
#endif
#include "head.h"
TableTennisPlayer::TableTennisPlayer(const string& fn,
const string& ln, bool ht) : firstname(fn),
lastname(ln), hasTable(ht) {}
void TableTennisPlayer::Name() const{
cout << lastname << ", " << firstname;
}
// RatedPlayer methods
RatedPlayer::RatedPlayer(unsigned int r, const string& fn,
const string& ln, bool ht) : TableTennisPlayer(fn, ln, ht){
rating = r;
}
RatedPlayer::RatedPlayer(unsigned int r, const TableTennisPlayer & tp)
: TableTennisPlayer(tp), rating(r)
{}
#include <iostream>
#include "head.h"
using namespace std;
int main(void){
TableTennisPlayer player1("Tara", "Boomdea", false);
RatedPlayer rplayer1(1140, "Mallory", "Duck", true);
rplayer1.Name(); // derived object uses base method
if (rplayer1.HasTable())
cout << ": has a table.\n";
else
cout << ": hasn't a table.\n";
player1.Name(); // base object uses base method
if (player1.HasTable())
cout << ": has a table";
else
cout << ": hasn't a table.\n";
cout << "Name: ";
rplayer1.Name();
cout << "; Rating: " << rplayer1.Rating() << endl;
// initialize RatedPlayer using TableTennisPlayer object
RatedPlayer rplayer2(1212, player1);
cout << "Name: ";
rplayer2.Name();
cout << "; Rating: " << rplayer2.Rating() << endl;
return 0;
}
输出:
Duck, Mallory: has a table.
Boomdea, Tara: hasn't a table.
Name: Duck, Mallory; Rating: 1140
Name: Boomdea, Tara; Rating: 1212
3. 派生类和基类的特殊关系
-
基类指针可以指向派生类对象,基类引用可以引用派生类对象;
即: 定义个基类指针或者引用,都可以用派生类对象赋给他们,好比作double->int
,但这样做会使得只能调用基类的方法。只要形参是基类,实参既可以是基类也可以是派生类。int main(){ RatedPlayer rplayer(1140, "Mallory", "Duck", true); TableTennisPlayer& rt = rplayer; TableTennisPlayer* pt = &rplayer; rt.Name(); pt->Name(); }
int main(){ TableTennisPlayer player("Mallory", "Duck", true); RatedPlayer& rt = player; RatedPlayer* pt = &player; } ERROR:E0144 "TableTennisPlayer *" 类型的值不能用于初始化 "RatedPlayer *" 类型的实体
-
对于非类方法的使用(引用)
void Show(const TableTennisPlayer& rt) { cout << "Name: "; rt.Name(); }
int main(){ TableTennisPlayer tplayer("Mallory", "Duck", true); RatedPlayer rplayer(1140, "Mallory", "Duck", true); Show(tplayer); Show(rplayer); }
-
对于非类方法的使用(指针==>和引用写法差不多)
Reference:
- 《C++ Primer Plus》第六版 Stephen Prata 著