C++ Primer Plus 第十三章知识点(一)

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 著
上一篇:C++ Primer小记 第六章 函数


下一篇:《C++ Primer》笔记 第15章 面向对象程序设计