Что является лучшим способом реализовать это в C ++ (без if-else). В C я могу инициализировать указатель на функцию, а затем просто вызывать указатели на функции. Поэтому, если вы посмотрите на класс C, некоторые объекты класса C используют только класс A, а некоторые класс B. Я больше знаком с C, чем с C ++.
class A {
public:
int func1();
int func2();
int func3();
};
class B:A {
public:
int func1() {x=1; A::func1();}
int func2() {A::func2(); x=1;}
int func3() {x=1; A::func2();}
};
class C {
public:
C::C(bool class_a) {_class_a = _class_a;}
void func_c_1()
{
if(_class_a) a.func1();
else b.func1();
}
void func_c_2()
{
if(_class_a) a.func2();
else b.func2();
}
void func_c_3()
{
if(_class_a) a.func3();
else b.func3();
}
private:
bool _class_a;
A a;
B b;
};
Ваш код не компилируется, и я мог бы неправильно понять вас, но если вам нужен класс, который делает разные вещи в зависимости от того, как он был создан, вам может помочь использование виртуальной базы с чисто виртуальными функциями и извлечение A и B из ее переопределения эти виртуальные функции.
class Base
{
public:
virtual int func1() = 0;
virtual int func2() = 0;
virtual int func3() = 0;
virtual ~Base(){} //it is important that this is virtual
};
class A: public Base
{
public:
virtual int func1(){
//do something
}
virtual int func2(){
//do something
}
virtual int func3(){
//do something
}
};
class B: public A
{
public:
virtual int func1(){
//do something else
((A*)this)->func1(); //call A's func1()
}
virtual int func2(){
//do something else
}
virtual int func3(){
//do something else
}
};
Base *a = new A;
Base *b = new B;
Base *c = a;
c->func1(); //does something
c=b;
c->func1(); //does something else
В противном случае, если вам нужны два разных класса (с разными типами), вы можете использовать шаблон. Если это то, что вы хотите комментировать, и я добавлю пример кода.
Также следует отметить, что ничто не мешает вам использовать указатели функций в C ++, хотя я бы не рекомендовал это делать. Вот пример кода только для хихиканья:
#include <functional>
class A
{
public:
int func1(){
//do something
return 1;
}
int func2(){
//do something
return 1;
}
int func3(){
//do something
return 1;
}
};
class B
{
public:
int func1(){
//do something else
return 1;
}
int func2(){
//do something else
return 1;
}
int func3(){
//do something else
return 1;
}
};
class C
{
public:
C(bool useA)
{
if(useA) {
func1 = std::bind(&A::func1,a_);
func2 = std::bind(&A::func2,a_);
func3 = std::bind(&A::func3,a_);
}
else {
func1 = std::bind(&B::func1,b_);
func2 = std::bind(&B::func2,b_);
func3 = std::bind(&B::func3,b_);
}
}
std::function<int()> func1;
std::function<int()> func2;
std::function<int()> func3;
private:
A a_;
B b_;
};
C c(true);
C c2(false);
c.func1();
Мне кажется, что вы пытаетесь понять наследование в C ++. Ваш код выглядит так, как будто он пытается получить другое поведение в зависимости от того, говорите ли вы, что это класс A или класс B. Если это так, это должно помочь:
#include <iostream>
using namespace std;
class A
{
public:
void foo() { cout << "A::foo\n"; }
void bar() { cout << "A::bar\n"; }
};
class B : public A
{
public:
void foo() { cout << "B::foo\n"; }
void fee() { cout << "B::fee\n"; }
};
main()
{
A* a = new A();
B* b = new B();
a->foo();
a->bar();
b->foo();
b->bar();
b->fee();
((a)b)->foo();
((a)b)->bar();
}
Я делаю класс A и (публично) заставляю класс B наследоваться от него. В пределах main первые 5 строк показывают поведение, которое вы ожидаете, но если вы хотите b
объект действовать как A
Я просто привел это к этому, и это делает. (Если вы запустите этот код, вы увидите, что окончательный foo
строка испускает A :: foo.)
Таким образом, поведение не навязывается во время строительства. Когда вы создаете объект, B :: foo переопределяет A :: foo. Но просто приведя к суперклассу, вы можете получить доступ к исходным функциям.
Обратите внимание, если вы хотите b.foo()
чтобы всегда выдавать «B :: foo», установите функцию foo в A на виртуальную:
class A
{
public:
virtual void foo() { cout << "A::foo\n"; }
void bar() { cout << "A::bar\n"; }
virtual ~foo() { /* any destructor code for the base class */ }
};
В этом случае, используете ли вы b->foo()
или же ((A*)b)->foo()
вывод будет «B :: foo». Среда выполнения будет работать с исходным типом объекта, а не с типом, к которому вы его приведете. Важный — Как только вы создадите виртуальную функцию в своем классе, вы должны создать виртуальный деструктор для этой функции. Если вы этого не сделаете, при удалении вашего объекта будет вызван только деструктор базового класса. (Когда вы используете виртуальные деструкторы, каждый деструктор вызывается из самого производного класса к основанию, по существу, раскручивая работу, которая была проделана при создании объекта.)
Надеюсь это поможет…