In my class design I ran into the following problem:
class MyData
{
int foo;
};
class AbstraktA
{
public:
virtual void A() = 0;
};
class AbstraktB : public AbstraktA
{
public:
virtual void B() = 0;
};
template<class T>
class ImplA : public AbstraktA
{
public:
void A(){ cout << "ImplA A()"; }
};
class ImplB : public ImplA<MyData>, public AbstraktB
{
public:
void B(){ cout << "ImplB B()"; }
};
void TestAbstrakt()
{
AbstraktB *b = (AbstraktB *) new ImplB;
b->A();
b->B();
};
The problem with the code above is that the compiler will complain that AbstraktA::A() is not defined.
Interface A is shared by multiple objects. But the implementation of A is dependent on the template argument. Interface B is the seen by the outside world, and needs to be abstrakt.
The reason I would like this is that it would allow me to define object C like this:
Define the interface C inheriting from abstrakt A.
Define the implementation of C using a different datatype for template A.
I hope I'm clear. Is there any way to do this, or do I need to rethink my design?
You have two paths of inheritance from AbstracktA, you implement AbstraktA::A() only in one of them, so the compiler complains.
You probably want to inherit virtually from AbstraktA in both case so that there is only one AbstraktA base object (add virtual before AbstraktA).
I forgot to add virtual destructors to the base classes. This leads to runtime malloc errors I believe.
AbstraktB *b = new ImplB;
b->A();
b->B();
delete b;
In debug mode, at the delete statement, GCC gives me:
malloc: *** error for object 0x60e2c4: pointer being freed was not allocated
I solved this by changing the base classes to:
class AbstraktA
{
public:
virtual ~AbstraktA(){};
virtual void A() = 0;
};
class AbstraktB : virtual public AbstraktA
{
public:
virtual ~AbstraktB(){};
virtual void B() = 0;
};
Related
I have a base class which serves as an interface (if I use that word correctly). The idea is that the base class has some derived classes that implement one virtual function of the base class. Then I also need another class that extends the base class (lets call it extended base). What I would like is that I can store a class derived from base into an extended base pointer.
MWE:
class Base {
public:
virtual ~Base();
virtual double value();
}
class Derived : public Base{
public:
double value() override {return 5;}
}
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase ();
virtual double value2(){return 10;}
}
int main() {
ExtendedBase * object;
object = new Derived();
std::cout << object->value(); //should give implementation in Derived, i.e. 5
std::cout << object->value2(); //should give implementation in ExtendedBase, i.e. 10
delete object;
return 0;
}
With this MWE I get a compile error at the second line in the main. error: cannot convert 'Derived*' to 'ExtendedBase*' in assignment object = new Derived();. Part of me understands why it doesn't work (although I can't explain), but I would like to know if I can get the desired behaviour in some other way.
P.S. Sorry about the bad question name, I couldn't think of another way to keep it short
P.S.2 I know raw pointers like this are not advised. In the future I will change to smart pointers but I don't think they are needed for this simple example
ExtendedBase and Derived are each derived from Base. If you want to use an ExtendedBase* pointer to point to a Derived object, you will need to derive Derived from ExtendedBase.
To use a different example,
class Feline{
virtual void run();
}
class Housecat : Feline{
void run() {}
}
class BigCat : Feline{
virtual void run();
virtual void roar();
}
Here Feline, Housecat, and BigCat are analogous to Base, Derived, and ExtendedBase. BigCat and Housecat are each Feline, but since Housecat is not a BigCat, you can't use a BigCat* pointer to point to a Housecat.
This is the desired behavior from a language architect perspective.
For instance, if you have
class Ship
{
public:
virtual void move() = 0;
}
class Steamboat : public Ship
{
public:
virtual void move() override { ... }
}
class Sailboat : public Ship
{
public:
virtual void move() override { ... }
virtual void setSails() { ... }
}
Now, you don't want a Steamboat to become a Sailboat all of a sudden, hence:
Steamboat* tootoo = new Sailboat;
cannot be valid.
That's why your code cannot work. Conceptually.
So giving a quick fix is not possible, because your concept is not really clear.
When you are assigning an address to a pointer that means you should be able to access all the members of the type the pointer is pointing to through the pointer.
For ex,
class B {};
class D : B {};
B *p = new D();
now through p, at least you can access all the members of base portion of the derived class.
But in your code,
ExtendedBase * object;
object = new Derived();
object should be able to access all the members of ExtendedBase portion of the derived class. But how is it possible as derived class is not derived from ExtendeBase. So compiler is throwing error.
You need to do some changes in your code to work.
To make base as interface (abstract class), you need to define at
least one member function as pure virtual.
If you want to access the member function of ExtendedBase through
Base pointer, you should define same function 'val' in your
ExtendedBase.
Below are the changes.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {};
virtual double value() = 0;
};
class Derived : public Base{
public:
~Derived() {};
double value() {
return 5;
}
};
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase () {};
double value()
{
return 10;
}
};
int main() {
Base *p = new Derived();
std::cout << p->value() << std::endl;
delete p;
Base *p1 = new ExtendedBase();
std::cout << p1->value() << std::endl;
delete p1;
return 0;
}
I have a basic base class and a couple of sub-classes which inherit from it.
Class Base{
public:
Base(){};
virtual ~Base();
virtual void foomethod()=0; //Marked as pure virtual
};
Class A : public Base{
A(){}; //Ctor
~A(){}; //Dtor
void foomethod(){ /* DO SOMETHING */ }
}
Class B : public Base{
B(){}; //Ctor
~B(){}; //Dtor
void foomethod(){ /* DO SOMETHING */ }
}
Use of the above is throwing an error in the following usage:
Base a = A();
Base b = B();
The compiler is complaining about the function foomethod() being pure virtual.
However, when the following is used, there is no problem.
A a = A();
B b = B();
I would have thought that the first instance should be accepted due to C++'s principles of polymorphism. I want to enforce a specific method implementation of the method in sub-classes. If it is marked as virtual only, there is not guarantee that it will be explicitly overrided.
There are several issues with your code, I'll try to get most of them:
You can't have a pure function without marking it as virtual
You can't create objects of an abstract Base class (there's no code for the methods)
When you write
Base b = A();
you're creating two objects and then assigning the A object to the Base b object. This cannot happen since Base is abstract but in cases where this can happen you could experience the slicing problem.
You marked the destructor as virtual in the derived classes but not in the Base (and no definition either), always mark it as virtual when using virtual polymorphism otherwise derived destructors will not be called
This is a more correct way of doing it:
#include <iostream>
using namespace std;
class Base{
public:
Base(){};
virtual ~Base() {};
virtual void foomethod()=0; //Marked as pure virtual
};
class A : public Base{
public:
A(){}; //Ctor
virtual ~A(){}; //Dtor
void foomethod(){ cout << "Hello from A"; }
};
class B : public Base{
public:
B(){}; //Ctor
virtual ~B(){}; //Dtor
void foomethod(){ /* DO SOMETHING */ }
};
int main() {
// Base obj; // Can't do that
Base *obj = new A();
obj->foomethod(); // A's one
delete obj;
return 0;
}
http://ideone.com/gvcL9S
Oh and there were some syntax errors here and there.. and a visibility problem if you intend to use those functions from the outside.. but I believe the excerpt was just a pseudocode one.
I have not programmed in c++ in a long time and want some simple behavior that no amount of virtual keywords has yet to produce:
class Base {
public:
int both() { return a(); }
};
class Derived : public Base {
protected:
int a();
};
class Problem : public Derived {
};
Problem* p = new Problem();
p.both();
Which gives me a compile-time error. Is this sort of behavior possible with c++? Do I just need forward declaration? Virtual keywords on everything?
No. You will have to use a pure virtual a in base.
class Base {
virtual int a() = 0;
int both() {
return a();
}
};
You should declare the a() function as a pure virtual method in the Base class.
class Base {
int both() {
return a();
}
virtual int a()=0;
};
Then implement the a() method in the Derived class
class Derived : public Base {
int a(){/*some code here*/}
};
And finally, Problem class doesn't see the both() method, since its private in Base. Make it public.
class Base {
public:
int both() {
return a();
}
};
Your function both() is private by default. Try:
class Base {
public:
int both() {
// ...
(In the future, it would be helpful if you tell us what the actual error message was.)
You need a() to be declared in class Base, otherwise the compiler doesn't know what to do with it.
Also, both() is currently a private method (that's the default for classes), and should be made public in order to call it from main.
You have multiple problems in your code :
unless you declare them public or protected, elements of a class are private as a default.
you need a virtual keyword to define a virtual function that would be callable in a parent.
new returns a pointer to Problem.
Here's a complete working code based on your test :
class Base {
protected:
virtual int a()=0;
public:
int both() {
return a();
}
};
class Derived : public Base {
private :
int a()
{
printf("passing through a!");
return 0;
}
};
class Problem : public Derived {
};
int main(void)
{
Problem* p = new Problem();
p->both();
}
tested on CodePad.
As others point out, you need to declare a() as pure virtual method of Base and change access to public to make your snippet work.
Here is another approach possible in c++: instead of virtual functions, you can use static polymorphism via the Curiously recurring template pattern:
template <class D>
class Base : public D
{
public:
int both() { return D::a(); }
};
class Derived : public Base<Derived>
{
public:
int a();
};
I'm posting this approach since you're asking what is possible in c++. In practice, virtual methods are most often a better choice because of their flexibility.
Coluld you provide a simple code example? (sorry C++ nube) and how to call a function from the class you are extending?
A bit useful example: :-)
class CImplementation
{
public:
void doFoo();
};
void CImplementation::doFoo()
{
//implementation
}
class IInterface
{
public:
virtual void foo()=0;
};
class DerivedFromImplementationAndInterface : public CImplementation, public IInterface
{
virtual void foo();
};
void DerivedFromImplementationAndInterface::foo()
{
doFoo();
}
//possible usage:
void method(IInterface& aInterface)
{
aInterface.foo();
}
void test()
{
IInterface* d = new DerivedFromImplementationAndInterface;
method(*d);
}
In C++, you can extend multiple classes, it's called multiple inheritance. Most probably this is what you're looking for. Please read a good book about multiple inheritance and C++ (a quick introduction: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr134.htm), because there are many pitfalls and details to pay attention to.
Example for multiple inheritance:
class A { ... };
class B { ... };
class C: public A, public B {}; // C inherits from A and B.
C++ doesn't explicitly have interfaces, the equivalent of an interface in Java is usually implemented with a class having only pure virtual functions (plus constructors, destructor, copy assignment):
#include <iostream>
// interface
class Fooable {
public:
virtual int foo() = 0;
virtual ~Fooable() {}
};
// base class
class Base {
public:
void non_virtual_function() { std::cout << "Base::non_virtual_function\n"; }
virtual void virtual_function() { std::cout << "Base::virtual_function\n"; }
};
// derived class, inherits from both Base "class" and Fooable "interface"
class Derived: public Base, public Fooable {
public:
virtual int foo() {
// call base class function
Base::non_virtual_function();
// virtual call to function defined in base class, overridden here
virtual_function();
}
virtual void virtual_function() {
// call base class implementation of virtual function directly (rare)
Base::virtual_function();
std::cout << "Derived::virtual_function\n";
}
void non_virtual_function() {
// not called
std::cout << "Derived::non_virtual_function\n";
}
};
int main() {
Derived d;
d.foo();
}
Not sure what you're asking:
class A
{
public:
void method();
};
class B
{
public:
void method();
};
class C : public A, public B
{
public:
void callingMethod();
};
void C::callingMethod()
{
// Here you can just call A::method() or B::method() directly.
A::method();
B::method();
}
Note that multiple inheritance can lead to really hard-to-solve problems and I would recommend to only use it when necessary.
The question as stated,
C++ is it possible to make a class extend one class and implement another?
does not make much sense. The answer to that is just "yes". You can derive from any number of classes: C++ fully support multiple inheritance.
So, given that the question as stated isn't really meaningful, it's at least possible that you meant to ask
C++ is it possible to make a class extend one class and thereby implement another?
The answer to this question is also yes, but it's not trivial. It involves virtual inheritance. Which is quite tricky.
Here's an example:
#include <iostream>
void say( char const s[] ) { std::cout << s << std::endl; }
class TalkerInterface
{
public:
virtual void saySomething() const = 0;
};
class TalkerImpl
: public virtual TalkerInterface
{
public:
void saySomething() const
{
say( "TalkerImpl!" );
}
};
class MyAbstractClass
: public virtual TalkerInterface
{
public:
void foo() const { saySomething(); }
};
class MyClass
: public MyAbstractClass
, public TalkerImpl
{};
int main()
{
MyClass().foo();
}
The virtual inheritance ensures that there is only one sub-object of type TalkerInterface in a MyClass instance. This has some counter-intuitive consequences. One is that "inheriting in an implementation" works, and another is that construction of that base class sub-object happens down in each MyClass constructor, and more generally down in the most derived class.
Cheers & hth.,
i have a problem in properly handling method overriding where an abstract class is present
inside my classes hierarchy.
I'll try to explain:
class AbstractClass{
public:
virtual void anyMethod() = 0;
};
class A : public AbstractClass {
void anyMethod() {
// A implementation of anyMethod
cout << "A";
}
};
class B : public AbstractClass {
void anyMethod() {
// B implementation of anyMethod
cout << "B";
}
};
AbstractClass *ptrA, *ptrB;
ptrA = new A();
ptrB = new B();
ptrA->anyMethod(); //prints A
ptrB->anyMethod(); //prints B
Ok..previous example work fine .. the concrete implementation of the AbstractClass
method anyMethod will be called at run time.
But AbstractClass is derived from another base class which has a method not virtual
called anyMethod:
class OtherClass {
public:
void anyMethod() {
cout << "OtherClass";
}
};
class AbstractClass : public OtherClass {
public:
virtual void anyMethod() = 0;
};
//A and B declared the same way as described before.
Now , if i try something like that:
ptrA = new A();
ptrB = new B();
ptrA->anyMethod(); //prints OtherClass
ptrB->anyMethod(); //prints OtherClass
What am I misunderstanding?
Is there any solution for making ptrA and ptrB printing A and B without using cast, typeid, etc?
Why don't you do:
class OtherClass
{
public:
virtual void anyMethod()
{
cout << "OtherClass";
};
}
That should solve your problems
If anyMethod was declared virtual in the base class to which you have a pointer or reference, it should be looked up virtually and print A and B correctly. If it wasn't, then there is nothing you can do (beyond changing it to be virtual).
I think that if the method in OtherClass that you want to override in A and B is NOT virtual, then the override is not implicit.
I believe there's a way to Explicitly override the functions, look that up.
DeadMGs answer is of course correct. But, if you cannot change OtherClass Methode (e.g. it's from a third party lib) you might want to try this:
Are the pointers ptrA and ptrB of type OtherClass or AbstractClass in your lower example?
If they are OtherClass I would expect the behaviour you described. You could try casting the pointer to AbstractClass then:
dynamic_cast<AbstractClass*>(ptrA)->anyMethod();
As far as I can see from your code OtherClass::anyMethod() is not a virtual and already implemented. It should work as you described if you define it as virtual
I think that your declaration for the second case is:
OtherClass* ptrA; and not AbstractClass *ptrA;
if you declared like the first case , there's no problem because the method is virtual,but if you declare as OtherClass , the compiler will not find virtual and bind to the adress of this method without using vtble.
thanks for the answers.. helped me a lot to understand the problem.
In effect I posted some wrong code, because i was misunderstanding the real problem.
Anyway, i think i partially solved my problem.
Here's the code:
#include <iostream>
`` using namespace std;
class Other{
public:
void foo(){
cout << "Other\n";
}
void foo(int a){}
};
class Abstract : public Other{
public:
virtual void foo() {};
virtual void foo(int c){
Other::foo(c);
}
};
class A : public Abstract{
public:
void foo(){
cout << "A\n";
}
};
class B : public Abstract{
public:
void foo(){
cout << "B\n";
}
};
int main(){
cout << "main\n";
Abstract * ptrA = new A();
Abstract * ptrB = new B();
Other *o = new Other();
o->foo();
ptrA->foo();
ptrB->foo();
ptrB->foo(3); //can't no more use the method foo with different signatures implemented in the base class Other, unless I explicitly redefined in the class Abstract
dynamic_cast<Other*>(ptrB)->foo(3);//can't dynamic_cast from derived to base
I was making two errors:
In my real code (not the simplified version posted before) i forgot to declare virtual
the function foo()
Even declaring virtual wasn't enough. In fact all the implementations of that function must be wrapped inside the class Abstract to become visible to the subclasses A and b. Otherwise wont't compile.
I don't know if it could be a clean solution..in fact that way I need to wrap all foo method signatures.