差不多看完了林锐的《高质量程序设计指南——C++/C语言》,觉得里面提到的一些注意点和技巧对初学者还是挺不错的,花了点时间编写了一个类的实例,包括了书中提到的一些技巧和注意点。
//Player.h
/***************
Written by zlj
***************/
//通过预处理命令,解决头文件重复包含的问题
#ifndef _PLAY_
#define _PLAY_
//#define TEST
#include <iostream>
#include <new>
class Player {
public:
Player(); //构造函数
Player(int length); //构造函数重载
Player(const Player& other); //拷贝构造函数
Player& operator =(const Player& other);
virtual ~Player(); //析构函数: 对于有派生类的类,析构函数要声明为virtual
virtual void Func();
/*
入口函数:
只需提供基类接口,而无需提供派生类实现细节
声明为static,表示该函数不依赖于对象而存在,相当于全局函数
*/
static Player* Creat();
#ifdef TEST
static int test; //静态数据成员,在对象创建之前就存在,被该类所有对象共享,相当于全局静态变量
void TestHideOne();
virtual void TestHideTwo();
void TestConst() const; //const表示该成员函数不能修改类的数据成员
#endif
/*
"protected"访问控制使派生类可以访问基类成员
注: 派生类无法访问基类的private成员
*/
protected:
int m_length; //在类的成员函数前加"m_"有利于区分
};
class VideoPlayer : public Player { //继承Player类
public:
VideoPlayer();
VideoPlayer(int length, int type);
VideoPlayer(const VideoPlayer& other);
VideoPlayer& operator =(const VideoPlayer& other);
~VideoPlayer();
virtual void Func(); //覆盖(overriding),基类成员函数必须声明为virtual,C++正式通过该机制实现了动态绑定
#ifdef TEST
void TestHideOne(); //隐藏,基类无virtual
virtual void TestHideTwo(int x); //隐藏,无论基类有无virtual
#endif
private:
int m_type;
};
#endif
//Player.cpp
#include "Player.h"
/*
类的成员函数在类外定义,const、static、virtual该怎么放?
const关键字必须同时出现在声明和定义处
static和virtual关键字只允许放在class body里的声明处
*/
Player::Player(): m_length(0) { //初始化列表
cout << "Player" << endl;
}
Player::Player(int length): m_length(length) {
cout << "Player(int length)" << endl;
}
Player::Player(const Player& other) {
cout << "Player::Player(const Player& other)" << endl;
m_length = other.m_length;
}
Player& Player::operator=(const Player& other) {
//(1)检查自赋值
if(this != &other) {
//(2)对类的数据成员赋值
cout << "Player& Player::operator =(const Player& other)" << endl;
m_length = other.m_length;
}
//(4)返回本对象的引用
return *this;
}
Player::~Player() {
cout << "~Player" << endl;
}
void Player::Func() {
cout << endl;
cout << "Player::Func()" << endl;
cout << "length: " << m_length << endl;
cout << endl;
}
Player* Player::Creat() {
return new(nothrow) VideoPlayer;
}
/*在派生类的构造函数中应显示调用基类的构造函数*/
VideoPlayer::VideoPlayer(): Player(), m_type(0) {
cout << "VideoPlayer" << endl;
}
/*派生类在初始化列表里调用基类特定的构造函数以向它传递参数*/
VideoPlayer::VideoPlayer(int length, int type): Player(length), m_type(type) {
cout << "VideoPlayer(int length, int type)" << endl;
}
/*在派生类的拷贝构造函数中调用基类的拷贝构造函数以向它传递参数*/
VideoPlayer::VideoPlayer(const VideoPlayer& other): Player(other) {
cout << "VideoPlayer::VideoPlayer(const VideoPlayer& other)" << endl;
m_type = other.m_type;
}
VideoPlayer& VideoPlayer::operator=(const VideoPlayer& other) {
//(1)检查自赋值
if(this != &other) {
//(2)调用基类的赋值函数,对基类的数据成员赋值
Player::operator =(other);
//(3)对派生类的数据成员赋值
cout << "VideoPlayer& VideoPlayer::operator =(const VideoPlayer& other)" << endl;
m_length = other.m_length;
}
//(4)返回本对象的引用
return *this;
}
VideoPlayer::~VideoPlayer() {
cout << "~VideoPlayer" << endl;
}
void VideoPlayer::Func() {
cout << endl;
cout << "VideoPlayer::Func()" << endl;
cout << "length: " << m_length << endl;
cout << "type: " << m_type << endl;
cout << endl;
}
#ifdef TEST
int Player::test = 7777; //非const静态数据成员的初始化必须放在类外,且不能放在头文件中
void Player::TestHideOne() {
cout << "Player::TestOne()" << endl;
}
void Player::TestHideTwo() {
cout << "Player::TestTwo()" << endl;
}
void Player::TestConst() const {
m_length = 0000;
}
void VideoPlayer::TestHideOne() {
cout << "VideoPlayer::TestOne()" << endl;
}
void VideoPlayer::TestHideTwo(int x) {
cout << "VideoPlayer::TestOne(int x)" << endl;
}
#endif
//main.cpp
#include <iostream>
#include "Player.h"
int main()
{
cout << "--------(1)--------" << endl;
VideoPlayer vpa(7, 77);
VideoPlayer vpb(vpa); //调用拷贝构造函数
vpb = vpa; //调用赋值函数
cout << endl << endl << endl;
cout << "--------(2)--------" << endl;
Player *pl = Player::Creat(); //Creat()返回一个指向派生类的指针
pl->Func(); //通过指向派生类的基类指针实现动态绑定
#ifdef TEST
cout << "static member test = " << test << endl;
pl->TestHideOne(); //调用的是基类中的函数
pl->TestHideTwo(); //调用的是基类中的函数
pl->TestHideTwo(7); //出错,不存在
pl->TestConst(); //出错,const成员函数不能修改类的数据成员
#endif
delete pl; //如果基类析构函数没有声明为virtual,这里就会出问题
return 0;
}