是否可以在 C++ 中的 2 个或更多文件中定义一个类?

发布于 2024-10-11 23:26:26 字数 87 浏览 9 评论 0原文

我知道可以在多个文件中进行类实现(是的,我知道这是一个坏主意),但我想知道是否可以在单独的文件中编写类定义而不会出现重新定义错误(也许有一些技巧,不然的话……)

I know it's possible to do class implementation in more than one file(yes, I know that this is bad idea), but I want to know if it's possible to write class definition in separate files without getting a redefinition error (maybe some tricks, or else...)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

木有鱼丸 2024-10-18 23:26:26

不,不是同一个班级,但为什么呢?

您可以在两个不同的头文件中在同一命名空间中定义两个具有相同名称的类(相同的签名!这实际上是同一个类,只是以两种方式定义),然后编译您的程序(如果您的源文件不这样做) t 包括两个标头。您的应用程序甚至可以链接,但在运行时,事情将不会按您的预期工作(这将是未定义的行为!),除非类相同。

请参阅查尔斯·贝利的回答以获得更正式的解释。


编辑:

如果您想要的是由多个文件定义一个类,为了(例如)向您的类添加一些自动生成的函数,您可以#include在你们班级的中间。

/* automatically generated file - autofile.gen.h */
void f1( ) { /* ... */ }
void f2( ) { /* ... */ }
void f3( ) { /* ... */ }
/* ... */

/* your header file with your class to be expanded */
class C
{
    /* ... */
    #include "autofile.gen.h"
    /* ... */
};

No, not the same class, but why would you?

You could define two classes with the same name in the same namespace (the same signature! That will actually be the same class at all, just defined in two ways) in two different header files and compile your program, if your source files don't include both headers. Your application could even be linked, but then at runtime things won't work as you expect (it'll be undefined behavior!), unless the classes are identical.

See Charles Bailey's answer for a more formal explanation.


EDIT:

If what you want is to have a single class defined by more than one file, in order to (for example) add some automatically generated functions to your class, you could #include a secondary file in the middle of your class.

/* automatically generated file - autofile.gen.h */
void f1( ) { /* ... */ }
void f2( ) { /* ... */ }
void f3( ) { /* ... */ }
/* ... */

/* your header file with your class to be expanded */
class C
{
    /* ... */
    #include "autofile.gen.h"
    /* ... */
};
前事休说 2024-10-18 23:26:26

不像 C# 中的 partial 关键字那样干净整洁,但是,您可以将类拆分为多个头文件:

class MyClass
{
#include "my_class_aspect1.h"
#include "my_class_aspect2.h"
#include "my_class_aspect3.h"
};

#include "my_class_aspect1.inl"
#include "my_class_aspect2.inl"
#include "my_class_aspect3.inl"

Not as nice and clean as the partial keyword in C#, but yes, you can split your class into multiple header files:

class MyClass
{
#include "my_class_aspect1.h"
#include "my_class_aspect2.h"
#include "my_class_aspect3.h"
};

#include "my_class_aspect1.inl"
#include "my_class_aspect2.inl"
#include "my_class_aspect3.inl"
小草泠泠 2024-10-18 23:26:26

是的,你可以。每个定义必须出现在单独的翻译单元中,但对多个定义有严格的限制。

每个定义必须由相同的标记序列组成,并且在每个定义中相应的名称必须引用相同的实体(或类本身定义中的实体)。

有关完整详细信息,请参阅 ISO 14882:2003 的 3.2 [basic.def.odr] / 5。

Yes, you can. Each definition must occur in a separate translation unit but there are heavy restrictions on multiple definitions.

Each definition must consist of the same sequence of tokens and in each definition corresponding names must refer to the same entity (or an entity within the definition of the class itself).

See 3.2 [basic.def.odr] / 5 of ISO 14882:2003 for full details.

一片旧的回忆 2024-10-18 23:26:26

好吧...

如果您有 1 个头文件,如下所示

ClassDef1.h:

class ClassDef
{
protected:
   // blah, etc.

public:
   // more blah

和另一个头文件,如下所示

ClassDef2.h:

public:
    // Yet more blah.
};

该类将有效地在 2 个文件中定义。

除了那种诡计之外..据我所知,不,你不能。

Well sort of ...

If you have 1 header file as follows

ClassDef1.h:

class ClassDef
{
protected:
   // blah, etc.

public:
   // more blah

and another as follows

ClassDef2.h:

public:
    // Yet more blah.
};

The class will effectively have been defined across 2 files.

Beyond that sort of trickery .. AFAIK, no you can't.

寄人书 2024-10-18 23:26:26

我知道这是一篇迟到的帖子,但一个朋友刚刚问了我一个类似的问题,所以我想我应该发布我们的讨论:

据我了解,你想做 ThinkingStiff,这在 C++ 中是不可能的。我认为您想要 C# 中的“部分类”之类的东西。

请记住,.NET 中的“部分类”是必要的,因此您不必将整个实现放入一个大源文件中。与 C++ 不同,.NET 不允许实现与声明分开,因此需要“部分类”。所以,拉菲德,这不是一个很好的功能,而是一个必要的功能,恕我直言,这是对轮子的重新发明。

如果您的类定义太大,您需要将其拆分为多个源文件,那么它可能会拆分为更小的、解耦的类,并且主类可以使用将它们联系起来的中介设计模式全部在一起。

如果您希望隐藏私有成员,例如在开发商业库时并且您不希望放弃知识产权(或对此影响的暗示),那么您可以使用纯抽象类。这样,标头中的所有内容都是简单的类,其中包含所有公共定义 (API) 和用于创建其实例的工厂函数。所有实现细节都在您的源文件中。

另一种替代方案与上面类似,但使用普通类(不是纯虚拟类),但仍然仅公开公共接口。在源文件中,您在无名命名空间内完成所有工作,必要时可以包含类定义中的friend函数等。还有更多工作,但是一个合理的技术。

粗体显示了您在解决问题时可能需要查找和考虑的内容。

I know this is a late post, but a friend just asked me a similar question, so I thought I would post our discussion:

From what I understand you want to do ThinkingStiff, it's not possible in C++. I take it you want something like "partial class" in C#.

Keep in mind, "partial class" in .NET is necessary so you don't have to put your entire implementation in one big source file. Unlike C++, .NET does not allow your implementation to be separate from the declaration, therefore the need for "partial class". So, Rafid it's not a nice feature, it's a necessary one, and a reinvention of the wheel IMHO.

If your class definition is so large you need to split it across more than one source file, then it can probably be split into smaller, decoupled classes and the primary class can use the mediator design pattern that ties them all together.

If your desire is to hide private members, such as when developing a commercial library and you don't wish to give away intelectual property (or hints to that affect), then you can use pure abstract classes. This way, all that is in the header is simple class with all the public definitions (API) and a factory function for creating an instance of it. All the implementation details are in your source file(s).

Another alternative is similar to the above, but uses a normal class (not a pure virtual one), but still exposes only the public interface. In your source file(s), you do all the work inside a nameless namespace, which can include friend functions from your class definition when necessary, etc. A bit more work, but a reasonable technique.

I bolded those things you might want to lookup and consider when solving your problem.

哎呦我呸! 2024-10-18 23:26:26

这是 C# 的优点之一,但不幸的是 C++ 不支持它。

This is one of the nice features of C#, but unfortunately it is not supported in C++.

樱花细雨 2024-10-18 23:26:26

是的。通常,人们将声明部分放在.h文件中,然后将函数体实现放在.cpp文件中
将声明放入 .h 文件中,然后在任意多个文件中实现,但每个文件中都包含 .h。

但是,您不能在多个文件中实现同一件事

Yes. Usually, people put the declaration part in .h file and then put the function body implementations in .cpp file
Put the declarations in a .h file, then implement in as many files as you want, but include the .h in each.

But, you cannot implement the same thing in more than one file

岁月染过的梦 2024-10-18 23:26:26

也许像基于策略的设计之类的东西可以解决问题?多重继承使您能够以其他语言无法做到的方式来组合类。当然,MI 也存在一些问题,因此请确保您知道自己在做什么。

Perhaps something like policy based design would do the trick? Multiple Inheritience gives you the possiblity to compose classes in ways you can't in other languages. of course there are gotchas associated with MI so make sure you know what you are doing.

等风来 2024-10-18 23:26:26

简短的回答是肯定的,这是可能的。正确的答案是否定的,您永远不应该考虑这样做(如果您无视该指令,您将受到其他程序员的鞭打)。

The short answer is yes, it is possible. The correct answer is no, you should never even think about doing it (and you will be flogged by other programmers should you disregard that directive).

未蓝澄海的烟 2024-10-18 23:26:26

您可以将成员函数的定义拆分为其他翻译单元,但不能拆分为类本身。为此,您需要使用预处理器技巧。

// header file with function declarations
class C {
public:
    void f(int foo, int bar);
    int g();
};

// this goes into a seperate file

void C::f(int foo, int bar) {
    // code ...
}

// this in yet another
void C::g() {
    // code ...
}

You can split the definitions of the member functions into other translation units, but not of the class itself. To do that, you'd need to do preprocessor trickery.

// header file with function declarations
class C {
public:
    void f(int foo, int bar);
    int g();
};

// this goes into a seperate file

void C::f(int foo, int bar) {
    // code ...
}

// this in yet another
void C::g() {
    // code ...
}
庆幸我还是我 2024-10-18 23:26:26

您想要在两个标头之间拆分肯定是有原因的,所以我的猜测是您确实希望将 2 个类连接在一起以形成单个(第三个)类的组件。

There must be a reason why you want to split between two headers, so my guess is that you really want 2 classes that are joined together to form components of a single (3rd) class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文