HOUR 9 Moving into Advanced Classes

const Member Functions

如果声明成员函数为const类型,那就意味着该函数没有权限修改类中的任何值,const声明在括号后面:

void displayPage() const

 如果想取变量的值,就可以使用const成员函数了,避免了不小心修改了变量。const成员函数如果编程时修改了成员变量的值,那么编译器会报错。应当尽可能多的使用const成员函数。

例如:

void setSpeed(int newSpeed);/用来设置速度,所以不可以是const
int getSpeed() const; //用来获取速度,可以加上const限定,避免误改

Organizing Class Declarations adn Function Definitions

  正规的写class都是类的声明和类的定义分开,声明部分在hpp头文件中,定义在cpp中,两个文件同名即可,因为类用户不关心类具体如何实现的,客户只关注类中包含哪些数据、action等,而要知道这些,客户只需要看你的头文件就可以了。

inline implementation

C++的类中的members function想要实现内联函数,有两种方法

  • 按照普通的inline定义方法,在函数前面写个inline
  • 在类声明的时候,直接将函数体写到类内部,编译器自动内联

 

Classes with other Classes as Member Data一种常用的创建复杂类的方法是,在类内声明其他简单的类作为其成员。

例如,你可能已经有了Wheel, Motor, Transmission 等类,当你定义一个Car 类的时候,从这样的角度去定义(has-a 关系):

一辆车有一组轮子、有一个motor, 有一个变速箱。

考虑下面一个例子,来理解这一概念:

一个Rectangle类,由四条线组成,每条线由两个点定义,一个点由(x,y)坐标表示,具体看下面的完整示例,so far so good.  

#ifndef RECTANGLE_H
#define RECTANGLE_H

#include <iostream>

class Point
{
    //no constructor, use default
public:
    void setX(int newX) { x = newX;}
    void setY(int newY) {y = newY;}
    int getX() const {return x;}
    int getY() const {return y;}
    int test;

private:
    int x;
    int y;

};

class Rectangle
{
public:
    Rectangle(int newTop, int newLeft, int newBottom, int newRight);
    ~Rectangle() {};

    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 getUpperRight() const { return upperRight;}
    Point getBottomLeft() const {return lowerLeft;}
    Point getBottomRight() const {return lowerRight;}

    void setUpperLeft(Point location);
    void setUpperRight(Point location);
    void setLowerLeft(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 right;
    int bottom;
};



#endif // RECTANGLE_H
Rectangle.h
#include "rectangle.h"


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::setUpperRight(Point location)
{
    upperRight = location;
    upperLeft.setY(location.getY());
    lowerRight.setX(location.getX());
    top = location.getY();
    right = 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::setTop(int newTop)
{
    top = newTop;
    upperLeft.setY(top);
    upperRight.setY(top);
}

void Rectangle::setBottom(int newBottom)
{
    bottom = newBottom;
    lowerLeft.setY(bottom);
    lowerRight.setY(bottom);
}

void Rectangle::setLeft(int newLeft)
{
    left = newLeft;
    lowerLeft.setX(left);
    upperLeft.setX(left);
}

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);
}
Rectangle.cpp
#include <QCoreApplication>
#include "rectangle.h"
#include <iostream>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Rectangle myRectangle(50, 30, 10, 80);
    int areaShow = myRectangle.getArea();
    std::cout << "The area is " << areaShow << std::endl;

    Point upperLeft = myRectangle.getUpperLeft();
    std::cout << "UpperLeft cordinate is ( " << upperLeft.getX() << "," << upperLeft.getY() << ")\n" ;

    Rectangle hiRectangle;
    areaShow = hiRectangle.getArea();
    std::cout << "area is " << areaShow << std::endl;
    return a.exec();
}
main.cpp

Summary

  • 使用类可以有效的提高代码重用性,例如word里面的拼写检查,可以直接移植到网页编辑器中,不需要从轮子造
  • 类的使用可以让程序更加可靠。面向object让任务分割开来,思维量大大减小,也更容易找出bug

Q&A

Q. 为什么要用const限定部分成员函数

A. 在不允许修改成员变量的函数中,加上const限定可以让编译器帮你界定一些愚蠢的错误,例如

//getSpeed()函数中包含这行
if(speed = 100)
    cout << "Max Speed Reached\n";

很明显,这里有一个错误,逻辑判断speed == 100?错误的写成赋值了,这样的话变量speed被悄悄的修改了,而且很难发现。如果你当时加上const限定,编译器就识别出来了

 

                                      

posted @ 2018-03-15 18:56  一只大公鸡  阅读(219)  评论(0)    收藏  举报