Можно ли определить класс в 2 или более файла в C ++? - PullRequest
3 голосов
/ 13 января 2011

Я знаю, что можно реализовать класс в нескольких файлах (да, я знаю, что это плохая идея), но я хочу знать, возможно ли написать определение класса в отдельных файлах без ошибки переопределениянекоторые хитрости, или еще ...)

Ответы [ 11 ]

4 голосов
/ 13 января 2011

Нет, не того же класса, но зачем вам?

Вы можете определить два класса с одним и тем же именем в одном и том же пространстве имен (одну и ту же сигнатуру! На самом деле это будет один и тот же класс, только что определенный двумя способами) в двух разных заголовочных файлах и скомпилировать вашу программу, если ваш исходный код файлы не включают оба заголовка. Ваше приложение может быть даже связано, но тогда во время выполнения все будет работать не так, как вы ожидаете (это будет неопределенное поведение!), Если классы не идентичны.

См. Ответ Чарльза Бейли для более формального объяснения.


EDIT:

Если вы хотите, чтобы один класс определялся более чем одним файлом, для того, чтобы (например) добавить некоторые автоматически сгенерированные функции в ваш класс, вы можете #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"
    /* ... */
};
3 голосов
/ 13 января 2011

Не так красиво и чисто, как ключевое слово partial в C #, но да, вы можете разбить свой класс на несколько заголовочных файлов:

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"
2 голосов
/ 13 января 2011

Ну вроде ...

Если у вас есть 1 заголовочный файл следующим образом

ClassDef1.h:

class ClassDef
{
protected:
   // blah, etc.

public:
   // more blah

и еще один следующий

ClassDef2.h:

public:
    // Yet more blah.
};

Класс будет эффективно определен в 2 файлах.

Помимо такого рода хитрости .. AFAIK, нет, ты не можешь.

1 голос
/ 07 апреля 2013

Я знаю, что это поздний пост, но друг только что задал мне похожий вопрос, поэтому я решил опубликовать наше обсуждение:

Из того, что я понимаю, вы хотите сделать ThinkingStiff, это невозможно вC ++.Я так понимаю, вы хотите что-то вроде «частичного класса» в C #.

Имейте в виду, «частичный класс» в .NET необходим, поэтому вам не нужно помещать всю реализацию в один большой исходный файл.В отличие от C ++, .NET не позволяет отделить реализацию от объявления, поэтому необходим «частичный класс».Итак, Rafid это не приятная особенность, это необходимая вещь и переосмысление колеса IMHO.

Если ваше определение класса настолько велико, вам нужно разделить его на несколько исходных файлов, тогда он можетвероятно, можно разделить на более мелкие разделенные классы, и основной класс может использовать шаблон проектирования посредника , который связывает их все вместе.

Если вы хотите скрыть частные члены, например, при разработкекоммерческая библиотека, и вы не хотите отдавать интеллектуальную собственность (или намеки на это), тогда вы можете использовать чисто абстрактные классы .Таким образом, все, что находится в заголовке, это простой класс со всеми общедоступными определениями (API) и фабричной функцией для создания его экземпляра.Все подробности реализации находятся в ваших исходных файлах.

Другая альтернатива похожа на вышеприведенную, но использует обычный класс (не чисто виртуальный), но по-прежнему предоставляет только открытый интерфейс.В ваших исходных файлах вы выполняете всю работу внутри безымянного пространства имен , которое может включать функции friend из определения вашего класса, когда это необходимо, и т. Д. Немного больше работы, норазумная техника.

Я выделен теми вещами, которые вы, возможно, захотите найти и учесть при решении своей проблемы.

1 голос
/ 13 января 2011

Да, вы можете. Каждое определение должно находиться в отдельной единице перевода, но существуют строгие ограничения для нескольких определений.

Каждое определение должно состоять из одинаковой последовательности токенов, и в каждом определении соответствующие имена должны ссылаться на одну и ту же сущность (или сущность в определении самого класса).

См. Подробности в 3.2 [basic.def.odr] / 5 ISO 14882: 2003.

1 голос
/ 13 января 2011

Да. Обычно люди помещают часть объявления в файл .h, а затем помещают реализации тела функции в файл .cpp. Поместите объявления в файл .h, затем внедрите их в любое количество файлов, но включите .h в каждый.

Но вы не можете реализовать одно и то же в более чем одном файле

0 голосов
/ 13 января 2011

Должна быть причина, по которой вы хотите разделить два заголовка, поэтому я предполагаю, что вы действительно хотите, чтобы два класса были объединены вместе, чтобы сформировать компоненты одного (третьего) класса.

0 голосов
/ 13 января 2011

Краткий ответ - да, это возможно. Правильный ответ - нет, вы никогда не должны думать об этом (и другие программисты будут пороть вас, если не будете соблюдать эту директиву).

0 голосов
/ 13 января 2011

Возможно, что-то вроде основанного на политике дизайна сработает?Множественное наследование дает вам возможность создавать классы так, как это невозможно на других языках.Конечно, есть некоторые проблемы, связанные с ИМ, поэтому убедитесь, что вы знаете, что делаете.

0 голосов
/ 13 января 2011

Вы можете разделить определения функций-членов на другие единицы перевода, но не на сам класс. Чтобы сделать это, вам нужно сделать хитрость препроцессора.

// 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 ...
}
...