第九章 高级类
9.1 const成员函数
如果使用关键字const将成员函数声明为常量函数(常函数),则表明它不会修改任何类成员的值。要将函数声明为常量函数,可在括号后面添加关键字const:
void displayPage() const;
如果将函数声明为常函数,但其实现修改了成员,编译器就会报错。
对于那些不用来修改类成员的函数,应尽可能将其声明为常函数,这是一种良好的编程习惯。这样可让编译器发现您对成员变量的无意间修改,避免在运行阶段出现这些错误。
9.2接口和实现
略
9.3组织类声明和函数定义
在c++的源代码中,类的定义和实现通常是分开的。您在类中声明的每个函数都必须有定义。与常规函数一样,类函数也包含函数头与函数体。
定义必须放在编译器能够找到的文件中,大多数c++编译器都要求这种文件的扩展名为.cpp
虽然可以将声明放在源代码文件中,但是大多数程序员采取的做法是,将声明放在头文件中,其文件名与源代码文件相同,但扩展名为.hpp(或是不那么常见的.h或.hp)
因此,如果您将Tricycle类的声明放在文件Tricycle.hpp中,那么类函数的定义位于文件Tricycle.cpp中。通过使用预处理编译指令,可在.cpp文件中包含头文件。
#include "Tricycle.hpp"
将他们分开的原因是,类的客户不关心实现细节,他们需要知道的信息都包含在头文件中。
9.4内联实现
可将常规函数声明为内联,同样,也可将成员函数声明为内联的,为此,需要在返回类型前面指定关键字inline,如下所示:
inline int Tricycle::getSpeed() { return speed; }
也可将函数定义放在类声明中(也就是写在里面),这样函数将自动变成内联的,如下所示:
class Tricycle { public: int getSpeed() const { return speed; } void setSpeed(int newSpeed); };
程序清单9.1与9.2实现了Tricycle类的声明与实现的分离:
程序清单9.1 Tricycle.hpp
#include <iostream>
class Tricycle
{
public:
Tricycle(int initialAge);
~Tricycle();
int getSpeed() const { return speed; }
void setSpeed(int speed);
void pedal()
{
setSpeed(speed + 1);
std::cout << "\nPedaling;tricycle speed " << speed << " mph\n";
}
void brake()
{
setSpeed(speed - 1);
std::cout << "\nBraking;tricycle speed " << speed << " mph\n";
}
private:
int speed;
};
程序清单9.2 Tricycle.cpp
#include "Tricycle.hpp"
Tricycle::Tricycle(int initialAge)
{
setSpeed(initialAge);
}
Tricycle::~Tricycle()
{
std::cout << "Destructed\n";
}
void Tricycle::setSpeed(int newSpeed)
{
if (newSpeed >= 0)
{
speed = newSpeed;
}
}
int main()
{
Tricycle wichita(5);
wichita.pedal();
wichita.pedal();
wichita.brake();
wichita.brake();
wichita.brake();
return 0;
}
可以看到运行效果与笔记8 程序清单8.2是一样的。
9.5将其他类用作成员数据的类
创建复杂类时,经常将简单类作为其成员
程序清单9.3与9.4为例:(其实书上给的这个例子里面太多的初始化方法,俺表示无语)
程序清单9.3 Rectangle.hpp
#include <iostream>
class Point
{
public:
void setX(int newX) { x = newX; }
void setY(int newY) { y = newY; }
int getX() const { return x; }
int getY() const { return y; }
private:
int x;
int y;
};
class Rectangle
{
public:
Rectangle(int newTop,int newLeft,int newBottom,int newRight);
~Rectangle(){std::cout << "Destructed\n";}
int getTop() const {return top;}
int getLeft() const {return left;}
int getBottom() const {return bottom;}
int getRight() const {return right;}
Point getUpperLeft() const {return upperLeft;}
Point getLowerLeft() const {return lowerLeft;}
Point getUpperRight() const {return upperRight;}
Point getLowerRight() const {return lowerRight;}
void setUpperLeft(Point location);
void setLowerLeft(Point location);
void setUpperRight(Point location);
void setLowerRight(Point location);
void setTop(int newTop);
void setLeft(int newLeft);
void setBottom(int newBottom);
void setRight(int newRight);
int getArea() const;
private:
Point upperLeft;
Point upperRight;
Point lowerLeft;
Point lowerRight;
int top;
int left;
int bottom;
int right;
};
程序清单9.4 Rectangle.cpp
#include "Rectangle.hpp"
Rectangle::Rectangle(int newTop,int newLeft,int newBottom,int newRight)
{
top=newTop;
left=newLeft;
bottom=newBottom;
right=newRight;
upperLeft.setX(left);
upperLeft.setY(top);
upperRight.setX(right);
upperRight.setY(top);
lowerLeft.setX(left);
lowerLeft.setY(bottom);
lowerRight.setX(right);
lowerRight.setY(bottom);
}
void Rectangle::setUpperLeft(Point location)
{
upperLeft = location;
upperRight.setY(location.getY());
lowerLeft.setX(location.getX());
top = location.getY();
left = location.getX();
}
void Rectangle::setLowerLeft(Point location)
{
lowerLeft=location;
lowerRight.setY(location.getY());
upperLeft.setX(location.getX());
bottom = location.getY();
left = location.getX();
}
void Rectangle::setLowerRight(Point location)
{
lowerRight=location;
lowerLeft.setY(location.getY());
upperRight.setX(location.getX());
bottom = location.getY();
right = location.getX();
}
void Rectangle::setUpperRight(Point location)
{
upperRight = location;
upperLeft.setY(location.getY());
lowerRight.setX(location.getX());
top = location.getY();
right = location.getX();
}
void Rectangle::setTop(int newTop)
{
top = newTop;
upperLeft.setY(top);
upperRight.setY(top);
}
void Rectangle::setLeft(int newLeft)
{
left = newLeft;
upperLeft.setX(left);
lowerLeft.setX(left);
}
void Rectangle::setBottom(int newBottom)
{
bottom = newBottom;
lowerLeft.setY(bottom);
lowerRight.setY(bottom);
}
void Rectangle::setRight(int newRight)
{
right=newRight;
upperRight.setX(right);
lowerRight.setX(right);
}
int Rectangle::getArea() const
{
int width = right - left;
int height = top - bottom;
return (width*height);
}
int main()
{
Rectangle myRectangle(100,20,50,80);
int area = myRectangle.getArea();
std::cout<<"Area: "<<area<<std::endl;
std::cout<<"Upper Left X Coordinate: ";
std::cout<<myRectangle.getUpperLeft().getX()<<std::endl;
}