3. 成员函数的类内声明和类外实现

在 C++ 语言中,在编写代码时通常将类(和结构)拆分成声明和实现两部分。声明部分通常写在 .h 文件中,内部只写类的成员声明,供类的实现成员函数和使用此类创建对象时使用;而成员函数的实现部分(和静态成员变量的定义和初始化,后面才讲)通常写在 .cpp 文件中,通常实现部分会单独编译和链接。

以下面代码为例,此 main.cpp 文件中类 Square 的声明和实现都实现在一起,并且和使用此类的 main 函数写在同一个文件中。这样不利于模块化编程,也不利于类的重复利用。

// filename: main.cpp
#include <iostream>

class Square {
    public:
        Square(double l=1) : length(l) {
            std::cout << "边长为" << l << "的正方形被创建!" << std::endl;
        }
        ~Square() {
            std::cout << "边长为" << length << "的正方形被销毁!" << std::endl;
        }
        double get_length(void) {
            return  length * 4;
        }
    private:
        double length;
};

int main(int argc, char * argv[]) {
    Square s1(3);

    std::cout << s1.get_length() << std::endl;

    return 0;
}

下面将上述的类 Square 拆成声明放在文件 square.h 中,将类 Square 的实现部分放在文件 square.cpp 中。将 main 函数放在 main.cpp 中。拆分结构如下:

文件:square.h

#ifndef __SQUARE_H__
#define __SQUARE_H__

class Square {
    public:
        Square(double l=1);
        ~Square();
        double get_length(void);
    private:
        double length;
};

#endif  /* __SQUARE_H__ */

文件:square.cpp

#include <iostream>

#include "square.h"

Square::Square(double l) : length(l) {
    std::cout << "边长为" << l << "的正方形被创建!" << std::endl;
}

Square::~Square() {
    std::cout << "边长为" << length << "的正方形被销毁!" << std::endl;
}

double Square::get_length(void) {
    return  length * 4;
}

成员在类外实现时,需要使用 作用域限定符:: 来说明当前的函数属于某个类的成员函数。如果成员函数有缺省参数,则只能在声明时说明缺省参数的值,而在现实部分则不用给出缺省参数。

构造函数的初始化列表需要写在成员函数的实现部分。

文件:main.h

#include <iostream>
#include "square.h"

int main(int argc, char * argv[]) {
    Square s1(3);

    std::cout << s1.get_length() std::endl;

    return 0;
}

编译和运行结果如下:

weimz@mzstudio:~$ g++ -o square.o -c square.cpp
weimz@mzstudio:~$ g++ -o main.o -c main.cpp
weimz@mzstudio:~$ g++ -o main main.o square.o
weimz@mzstudio:~$ ./main
边长为3的正方形被创建!
12
边长为3的正方形被销毁!

实验

将你之前写过的类拆解成类内声明和类外实现。