С++ метод добавления к классу, определенному в файле заголовка

Мне интересно, можно ли добавлять методы в основную программу к существующему классу, определенному в файле заголовка. Например: В файле CFun.hpp указан class CFun, но в нашем party.cpp мы хотим добавить метод void hello() {cout << "hello" << endl;}; без редактирования CFun.hpp

Очевидно (к сожалению) конструкция:

#include "CFun.hpp"

class CFun
{
  public:
    void hello() {cout << "hello" << endl;};
};

не работает, возвращая ошибку Multiple declaration for 'CFun'

Можно ли заставить его работать без наследования классов?

Ответ 1

Нет, но вы можете добавить метод, который принимает ссылку/указатель на класс CFun - у вас просто не будет доступа к конфиденциальным данным:

void Hello(CFun &fun)
{
    cout << "hello" << endl;
}

Это, вероятно, лучшее, что вы сможете сделать. Как указано в litb - эта функция должна находиться в том же пространстве имен, что и CFun. К счастью, пространства имен, в отличие от классов, могут быть добавлены в несколько мест.

Ответ 2

Вы можете переопределить класс следующим образом:

#define CFun CLessFun
#include "CFun.hpp"
#undef CFun

class CFun : CLessFun
{
   public:
    void hello() {cout << "hello" << endl;};
};

Поместите это в новый заголовочный файл CMoreFun.hpp и укажите, что вместо CFun.hpp

Ответ 3

Нет, это невозможно. Может быть только одно определение любого конкретного класса, и оно должно быть полным определением, означающим, что вы не можете иметь частичные определения в разных местах, добавляя в класс участников.

Если вам нужно добавить функцию-член в класс, то либо вам нужно изменить определение класса (отредактировать CFun.hpp), либо получить новый класс из CFun и поместить туда hello().

Ответ 4

Ближайшим аналогом такого типа конструкции (добавлением функциональности к предопределенным классам) в С++ является шаблон Decorator. Это не совсем то, что вам нужно, но это может позволить вам делать то, что вам нужно.

Ответ 5

Это кажется очевидным прецедентом для наследования. Определите новый класс:

#include "CFun.hpp"

class CFun2 : public CFun
{
  public:
    void hello() {cout << "hello" << endl;};
};

Затем используйте CFun2 вместо CFun в исходном коде.

Ответ 6

Не знаю. Хотя вы можете сделать какую-то фальсификацию присяжных и создать решение namespace-y.

Ответ 7

Подумав об этом, вы можете сделать что-то страшное: найдите в CFun какую-нибудь функцию с нулевым типом возвращаемого значения и упоминайте только один раз во всем заголовке. Скажем void GoodBye().

Теперь создайте файл CFunWrapper.hpp с этим контентом:

#define GoodBye() Hello() { cout << "hello" << endl; } void GoodBye()
#include "CFun.hpp"
#undef GoodBye

Тогда только когда-либо включайте CFunWrapper.hpp вместо CFun.hpp.

Но не делайте этого, если у вас нет действительно веских оснований для этого. Он чрезвычайно подвержен взлому и может быть даже невозможен, в зависимости от содержимого CFun.hpp.

Ответ 8

class Party : class CFun

(ваш party.cpp)

наследует CFun файл, включая функцию hello().

Итак...

Party p;
p.hello();

Нет