对用户隐藏类的构造

C++: hide class construction from user

本文关键字:用户 隐藏      更新时间:2023-10-16

我正在开发一系列事件类。这些类包含从系统获取的信息。它们来自不同的性质,可能包含不同的消息,例如:一个可能的事件将包含一个巨大的数字列表,而另一个可能以字符串的形式携带查询信息。我想创建一个生成器函数,它创建正确类型的事件并返回给用户。

下面是一个演示:

main.cpp:

#include <iostream>
#include "A.h"
#include "dA.h"
using namespace std;
int main()
{
   cout << "Hello world!" << endl;
   A a = build(5);
   return 0;
}

Event.h:

#ifndef A_H_INCLUDED
#define A_H_INCLUDED
#include <iostream>
class A
{
public:
    friend A build(int x);
protected:
    A(int x);
private:
};
#endif // A_H_INCLUDED

event.cpp:

#include "A.h"
A::A(int x)
{
    {
        std::cout << "An";
        std::cout << x << std::endl;
    }
}
A build(int x)
{
    if(x == 5)
        return dA(x);
    return make(x);
}
特殊event.h

#ifndef DA_H_INCLUDED
#define DA_H_INCLUDED
#include <iostream>
#include "A.h"
class dA : public A
{
public:
protected:
    dA(int x);
};
#endif // DA_H_INCLUDED

特殊event.cpp:

#include "dA.h"
dA::dA(int x) : A(x)
{
    std::cout << "dAn";
}

正如你所看到的,所有的构造函数都是受保护的,目的是对用户隐藏构造——用户不应该无中生有地创建事件,只有系统可以——并保证构建函数将返回正确类型的事件。

编译时,得到:

error: 'build' was not declared in this scope
warning: unused variable 'a' [-Wunused-variable]

如果我把所有的东西放在同一个文件中,我可以编译,但是,我最终得到一个难以管理的大文件。请注意,上面的代码只是一个示例,我将使用的真正的类是巨大的,把所有的声明和实现都放在同一个文件中,一切都变得一团糟。

必须声明build函数。现在,你只告诉编译器它是Afriend,但你没有在全局作用域中声明它。

A.h头文件中添加一个原型:

A build(int x);

你似乎没有把文件正确地连接在一起。由于您似乎正在使用GCC(从错误消息判断),您可以通过两种方式完成:
  1. 将编译和链接结合在一起:

    $ g++ main.cpp event.cpp -Wall -g -o my_program
    

    在上面的命令中,您告诉GCC编译main.cppevent.cpp文件,并将它们链接在一起,生成my_program可执行文件。标志-Wall启用更多警告(这很好,我个人使用更多选项来启用大量警告),-g告诉GCC包括调试信息。

  2. 第二种方法是将这些文件分别编译成目标文件,然后在单独的步骤中将这些目标文件链接在一起:

    $ g++ main.cpp -c -Wall -g
    $ g++ event.cpp -c -Wall -g
    $ g++ main.o event.o -o my_program
    

    新的标志-c告诉GCC生成一个与源文件同名的目标文件,所以对于main.cpp,它将被命名为main.o。然后最后一个命令获取这些目标文件并将它们链接到可执行文件my_program中。

如果您有很多源文件,首选第二种方法,因为如果您更改了单个源文件,则无需再次编译所有源文件,只需更改的源文件即可。由于一直手动编写这些命令可能需要大量的工作,因此建议使用make等工具来自动执行这些任务。