1.3 C++基础知识_程序结构

本节讨论C++的程序结构。

在类外部定义函数

之前将函数在类中定义,现在首先将函数定义到类的外部,仅在类中申明。

注意定义在外部的函数,函数名前面需要加上Person::,表示属于Person类,其他规则和在类中定义一致。

单模块处理

当函数内容比较简短时,写在类中也可以,但是如果篇幅较大,最好还是在外部实现,这样代码会更简洁些。

假设一个团队在做某个设备:

  • 由A实现Person类(相当于Person模块);
  • 由B实现main,B会在main中使用Person类,但是不会关心Person类的具体实现,只关心怎么使用这个类;

那么,A需要创建两个文件:

  1. person.h
  2. person.cpp

其中头文件 person.h 需要提供给B使用,person.cpp 则由A自行保管维护即可。

B只需要实现一个文件 main.cpp 即可,在 main.cpp 文件中 include person.h 文件,然后使用person类。

person.h

person.h 的内容如下,在头文件中,只是定义了一个Person类。

通过person.h头文件,可以看到,Person类中的有私有成员name,age,也有公有成员setName函数和printfInfo函数。

这样,使用Person类的人就能很方便的知道,要想设置name,就需要通过setName函数,而不需要关心具体的函数实现。

#ifndef __PERSON_H_
#define __PERSON_H_

class Person {
private:
    char *name;
    int age;

public:
    void setName(char *name);

    void printfInfo();
};

#endif

person.cpp

person.cpp的内容如下,在cpp文件中,include person.h文件,然后实现Person类中的函数。

#include <stdio.h>
#include "person.h"

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

void Person::setName(char *name) {
    this->name = name;
}

void Person::printfInfo() {
    printf("name = %s, age = %d\n", name, age);
}

 main.cpp

在main.cpp中,通过person.h将Person类包含进来,然后就可以使用person类了。

#include <stdio.h>
#include "person.h"

int main(int argc, char **argv)
{
    Person per;

    per.setName("zhangsan");
    per.printfInfo();
}

Makefile

通过一个Makefile来实现编译和清除。

$^ 表示所有的依赖,$< 表示第一个依赖。

target=person

$(target): main.o person.o
    g++ -o $@ $^

%.o : %.cpp
    g++ -c -o $@ $<

clean:
    rm -f *.o $(target)

编译出来执行elf文件,结果符合预期,程序改写成功。

多模块处理

假设需要新增一个功能模块Dog,由C负责,那么团队的分工则变为:

  • 由A实现Person类;
  • 由B实现main,B会在main中使用Person/Dog类,但是不会关心Person/Dog类的具体实现,只关心怎么使用Person/Dog类;
  • 由C实现Dog类;

类似的,C需要实现两个文件:

  1. dog.h
  2. dog.cpp

与 person 类似,在dog.h中声明一个dog类,在dog.cpp中实现dog类。

dog.h

#ifndef __DOG_H_
#define __DOG_H_

class Dog {
private:
    char *name;
    int age;

public:
    void setName(char *name);

    void printfInfo();
};

#endif

dog.cpp

#include <stdio.h>
#include "dog.h"

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

void Dog::setName(char *name) {
    this->name = name;
}

void Dog::printfInfo() {
    printf("name = %s, age = %d\n", name, age);
}

main.cpp

修改main.cpp,将dog.h包含进来,然后就可以使用Dog类了。

 #include <stdio.h>
 #include "person.h"
 #include "dog.h"

 int main(int argc, char **argv)
 {
     Person per;
     Dog dog;

     per.setName("zhangsan");
     per.printfInfo();

     dog.setName("wangcai");
     dog.printfInfo();
 }

命名空间(namespace)

假设,需要在person.cpp和dog.cpp中,分别实现一个printVersion函数,打印对应模块的版本号。

 在person.h和dog.h中申明printVersion函数,注意并不是在类中声明

然后在main.cpp中调用。

此时,编译程序会报错,这是由于在dog.h和person.h中都有定义printVersion函数,编译器不知道要调用哪一个printVersion。

这个问题就涉及到命名空间了。

在实际工程中,可能会遇见相同名称的函数,当编译器遇见相同名称的函数时,需要根据命名空间来决定使用哪个函数。

首先修改person.h,dog.h,person.cpp,dog.cpp,分别设置两个作用域A和C。

 

 这时候编译就会报错,因为没有标明使用的是哪个域,编译器会报找不到类型声明。

 为了方便起见,将多余的代码先注释掉。

 

函数前面的A::和C::分别表示这个函数属于A和C的命名空间,声明命名空间后,代码可以编译成功,执行结果也符合预期。

类似的,也可以通过using namespace来决定要使用哪个命名空间,这时候,不冲突的对象可以不用加A::和C::,冲突的函数与之前一样,需要声明使用的命名空间是哪个。

 

 如果只要要使用某个命名空间中的某个对象,而不是全部的话,也可以单独using那个类。

 执行结果和之前是一样的。

小结

程序结构如下:

  1. 类定义(.h) / 类实现(.cpp);
  2. 命名空间;
    1. 在.h/.cpp文件中,使用namespace a { ... }设置命名空间;
    2. 在调用者源文件中:
      1. 直接使用:a::fun, a::fun2
      2. using声明:using a::fun; //以后调用fun即表示a::fun
      3. using编译:using namespace a;//以后直接调用fun,fun2即可

使用iostream

最后,再修改一下代码。

在C++中,通常使用 iostream 而不是stdio.h。

使用iostream,需要用cout替换printf,并且需要使用命名空间std。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值