С++ метод добавления к классу, определенному в файле заголовка
Мне интересно, можно ли добавлять методы в основную программу к существующему классу, определенному в файле заголовка.
Например:
В файле 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();
Нет