I am trying to learn inheritance in c++. I wrote some code to learn virtual functions.
#include <iostream>
using namespace std;
class A {
int a;
public:
A() {}
virtual int get_count() const = 0;
int get_A() { return a; }
};
class B : public A{
public:
int b;
B() {}
B(A& base)
: b(base.get_count()) {}
virtual int get_count() const { return 10; }
};
void func(A& base) {
B derived(base);
cout << derived.b;
}
int main() {
A base;
B derived;
func(derived);
}
When I try to compile I get this error:
test_inheritance_vir.cpp: In function ‘int main()’:
test_inheritance_vir.cpp:32: error: cannot declare variable ‘base’ to be of abstract type ‘A’
test_inheritance_vir.cpp:5: note: because the following virtual functions are pure within ‘A’:
test_inheritance_vir.cpp:10: note: virtual int A::get_count() const
Can you please tell me what I am doing wrong?
You are trying to instantiate an object of type A with A base;. It's not possible as A contains a pure virtual function. (get_count()) Suppose I tried calling base.get_count().
The method virtual int get_count() const = 0; is pure virtual. You can't create an object of a class that is abstract (or in other words - has a pure virtual member). If you want to create an object of A, remove the = 0 and define the function (with an empty body if you need):
virtual int get_count() const{};
should work.
The way you have implemented A (below) causes it to be an abstract base class.
class A
{
int a;
public:
A() {}
virtual int get_count() const = 0; // this is a pure virtual function
int get_A() { return a; }
};
It can only be used as a pointer to a derived class that implements the pure virtual functions:
int main()
{
B derived;
A* pA = new B; // this is okay
delete pA;
return 0;
}
The answers above are the technical reasons why it won't work, but there's a more insidious problem in that the design doesn't make sense. You're creating a B to add some functionality to your A. If you also create a C that extends A, do you really want to turn that into a B?
The classic example of inheritance is animals. Zebra and Giraffe are both Animals, so a class hierarchy would look like this
class Animal
{
stuff
}
class Zebra : public Animal
{
more stuff
}
class Giraffe : public Animal
{
different stuff
}
It doesn't make much sense to turn a Zebra into a Giraffe, though, even though both are animals.
Related
I have a base class B derived from an abstract class A. The idea of having abstract class A is to facilitate Dependency Injection and Mocking while unit testing. So A have no implementation. Almost like C# interface. All works fine.
Now I have a derived class D that is inherited from B. The problem now is D does not have an abstract class to facilitate DI or Mocking. Here is a little code that explains the problem:
class A // Abstract
{
public:
virtual String Identify() = 0;
};
class B : public A
{
public:
String Identify() {return "B"; }
};
class D : public B
{
public:
String D_Work() {return "D_Work"; }
};
So to use B, I do A *b = new B(); which is fine. The using class does not know the type B. new() is done by a factory or the object is just passed in.
But to use D, I either need the actual type (which I am trying to get away) or use type A and cast to call methods like A *d = new D(); ((D*)d)->D_Work()) (using c-style for simplicity) which again will require the user to know the type. Any thoughts on the design?
You can add another abstract class in between B and D:
class B : public A {
public:
string Identify() {return "B"; }
};
class C : public B {
public:
virtual string D_Work() = 0;
};
class D : public C {
public:
string D_Work() {return "D_Work"; }
};
See it work here: ideone
It looks like I may have misunderstood what you want. It seems you want to be able to continue using only an A pointer. In that case, I'd add a virtual D_Work() function to A that throws:
class A {
public:
virtual string Identify() = 0;
virtual string D_Work() { throw; } // If it's not defined, throw
};
See it work here: ideone
The other approach is that you have multiple interfaces I, J ,K, and pure methods in A like GetI() that return pointers to that interface.
Then All your implementation classes implement A, plus any other interfaces plus any of the GetX() methods.
Your interface is A,I,J,K, and that is all that is exposed. That is all that needs to be mocked.
Ultimately, the continuous updating of A to add new classes gets tiresome, so you invest in a different mechanism for getting the interfaces, probably based on a token declared in the interface class, and a template method in A that resolves the token and return type by calling an implementation method that does the same. Or you just give up and let the caller dynamic_cast to the interfaces.
Sometime soon you end up with COM, or something very like it.
class A;
{
virtual String Identify() = 0;
virtual I* GetI() { return nullptr;}
virtual J* GetJ() { return nullptr;}
virtual K* GetK() { return nullptr;}
};
class I
{
virtual void Work() =0;
};
class J
{
virtual void MoreWork() =0;
};
class B: A, I
{
void Work() {}
I* GetI() { return this;}
};
class C: A, J
{
void MoreWork() {}
I* GetJ() { return this;}
};
when a base class pointer points to the object of it's derived class and if a function being overridden we use virtual function to solve the problem . So that we can access the own function of derived class using the pointer.
Like this , i was thinking that if there a way which can be applied on virtual keyword in variable , so that we can access the latest version of a variable in derived class using pointer.
#include <iostream>
using namespace std;
class base
{
public:
int x;//but what about this , if we add virtual keyword here.
//it will give error if trying to do so .
//but can you tell me what can i do if i want to make use of it as virtual function
//if not please tell me why
virtual void display(void) //to call the recent version of display function we make use of virtual here
{
cout << "base\n";
}
};
class derived : public base
{
public:
int x;
void display(void)
{
cout << "derived\n";
}
};
int main(void)
{
base *p;
base ob1;
derived ob2;
p=&ob2;
p->x=100;//here i want to set 100 to the x of derived class not that x which has been inherited
//But it sets to the x of base class which i dont wanted
p->display();//here we can access the latest version of display function in derived class
return 0;
}
Please, No body ask me why i want to do so.I don't have any intention to do in my real code. i asked for the curiosity.
No, you cannot use virtual for fields, only for methods.
However you can simulate that by creating a function that returns a reference to a field:
class Base
{
private:
int x;
public:
virtual int& X() { return x; }
};
class Derived : public Base
{
private:
int x;
public:
virtual int& X() override { return x; }
};
int main()
{
Derived d;
Base* b = &d;
b->X() = 100; // will set d's x
}
You can't override member variables with the virtual keyword. You could, however, have virtual getters and setters that refer to different member variables in the base and derived classes to achieve a similar effect:
class base {
public:
virtual int getX() {
return x;
}
virtual void setX(int x) {
this->x = x;
}
private:
int x;
}
class derived : public base {
public:
int getX() {
return x;
}
void setX(int x) {
this->x = x;
}
private:
int x;
}
The other answers are totally fine but you can also use the much simpler syntax:
class base {
public:
virtual operator int&() { return x; };
virtual operator int() { return x; };
protected:
int x;
};
if you have a single variable that you'd wish to virtualize in your class.
The second declaration is only to avoid using a reference when you just need the value, while when assigning the reference is automatically chosen for you.
You can override these operators at will from classes derived from base.
class derived : public base {
public:
operator int() override { return x * 5; };
}
I tried this code:
class A
{
virtual void foo() = 0;
};
class B
{
virtual void foo() = 0;
};
class C : public A, public B
{
//virtual void A::foo(){}
//virtual void B::foo(){}
virtual void A::foo();
virtual void B::foo();
};
void C::A::foo(){}
void C::B::foo(){}
int main()
{
C c;
return 0;
}
It is OK when using the commented part, but when I try to write the definitions outside the class declaration, the compiler reports errors.
I am using the MSVC11 compiler, does anyone know how to write this?
I need to move the code into the cpp file.
Thank you~~
A function overrides a virtual function of a base class based on the name and parameter types (see below). Therefore, your class C has two virtual functions foo, one inherited from each A and B. But a function void C::foo() overrides both:
[class.virtual]/2
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
As I already stated in the comments, [dcl.meaning]/1 forbids the use of a qualified-id in the declaration of a (member) function:
When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers [...]"
Therefore any virtual void X::foo(); is illegal as a declaration inside C.
The code
class C : public A, public B
{
virtual void foo();
};
is the only way AFAIK to override foo, and it will override both A::foo and B::foo. There is no way to have two different overrides for A::foo and B::foo with different behaviour other than by introducing another layer of inheritance:
#include <iostream>
struct A
{
virtual void foo() = 0;
};
struct B
{
virtual void foo() = 0;
};
struct CA : A
{
virtual void foo() { std::cout << "A" << std::endl; }
};
struct CB : B
{
virtual void foo() { std::cout << "B" << std::endl; }
};
struct C : CA, CB {};
int main() {
C c;
//c.foo(); // ambiguous
A& a = c;
a.foo();
B& b = c;
b.foo();
}
You've got just one virtual function foo:
class A {
virtual void foo() = 0;
};
class B {
virtual void foo() = 0;
};
class C : public A, public B {
virtual void foo();
};
void C::foo(){}
void C::A::foo(){}
void C::B::foo(){};
int main() {
C c;
return 0;
}
I stepped into the same problem and accidentially opened a second thread. Sorry for that. One way that worked for me was to solve it without multiple inheritance.
#include <stdio.h>
class A
{
public:
virtual void foo(void) = 0;
};
class B
{
public:
virtual void foo(void) = 0;
};
class C
{
class IA: public A
{
virtual void foo(void)
{
printf("IA::foo()\r\n");
}
};
class IB: public B
{
virtual void foo(void)
{
printf("IB::foo()\r\n");
}
};
IA m_A;
IB m_B;
public:
A* GetA(void)
{
return(&m_A);
}
B* GetB(void)
{
return(&m_B);
}
};
The trick is to define classes derived from the interfaces (A and B) as local classes (IA and IB) instead of using multiple inheritance. Furthermore this approach also opens the option to have multiple realizations of each interface if desired which would not be possible using multiple inheritance.
The local classes IA and IB can be easily given access to class C, so the implementations of both interfaces IA and IB can share data.
Access of each interface can be done as follows:
main()
{
C test;
test.GetA()->foo();
test.GetB()->foo();
}
... and there is no ambiguity regarding the foo method any more.
You can resolve this ambiguity with different function parameters.
In real-world code, such virtual functions do something, so they usually already have either:
different parameters in A and B, or
different return values in A and B that you can turn into [out] parameters for the sake of solving this inheritance problem; otherwise
you need to add some tag parameters, which the optimizer will throw away.
(In my own code I usually find myself in case (1), sometimes in (2), never so far in (3).)
Your example is case (3) and would look like this:
class A
{
public:
struct tag_a { };
virtual void foo(tag_a) = 0;
};
class B
{
public:
struct tag_b { };
virtual void foo(tag_b) = 0;
};
class C : public A, public B
{
void foo(tag_a) override;
void foo(tag_b) override;
};
A slight improvement over adigostin's solution:
#include <iostream>
struct A {
virtual void foo() = 0;
};
struct B {
virtual void foo() = 0;
};
template <class T> struct Tagger : T {
struct tag {};
void foo() final { foo({}); }
virtual void foo(tag) = 0;
};
using A2 = Tagger<A>;
using B2 = Tagger<B>;
struct C : public A2, public B2 {
void foo(A2::tag) override { std::cout << "A" << std::endl; }
void foo(B2::tag) override { std::cout << "B" << std::endl; }
};
int main() {
C c;
A* pa = &c;
B* pb = &c;
pa->foo(); // A
pb->foo(); // B
return 0;
}
Assuming that the base classes A and B are given and cannot be modified.
I know there are many questions out there concerning MI, however, none seemed to answer my question. I have the following minimal example:
#include <iostream>
struct Base{
virtual void foo() = 0;
};
struct A : public virtual Base{
void foo(){
std::cout << "A::foo()" << std::endl;
}
void foo( int a){
std::cout << "A::foo(int a)" << std::endl;
}
};
struct B : public virtual Base{
virtual void foo( int a ) = 0;
};
struct C : public B,public A{
using A::foo;
};
int main( int argc, char* argv[]){
C c;
c.foo();
c.foo( 1 );
}
where Base, and B are entirely virtual classes and A provides all the implementation. However, the code does not compile but instead gives me the following error message
mh.cpp: In function ‘int main(int, char**)’:
mh.cpp:22:11: error: cannot declare variable ‘c’ to be of abstract type ‘C’
C c;
^
mh.cpp:17:12: note: because the following virtual functions are pure within ‘C’:
struct C : public B,public A{
^
mh.cpp:15:22: note: virtual void B::foo(int)
virtual void foo( int a ) = 0;
The behaviour I desire can be achieved by extending class C to
struct C : public B,public A{
using A::foo;
void foo( int a ){
A::foo( a );
}
};
However, I'd prefer not adding this redundant method. Is there some way I can achieve that result?
A::foo(int) can't override B::foo(int) unless A derives from B.
So, if you don't want to create the forwarding override in C, your alternatives are:
move the foo(int) pure virtual overload into Base
make A derive from B
restructure your interfaces so you don't need diamond-shaped virtual inheritance in the first place
No, if you inherit from a pure virtual class and you want to use this derived class (declare object of that type, not a pointer), you must implement all its pure virtual methods.
In the same manner you could ask the following:
class A
{
public:
virtual void foo()=0;
virtual void hello()=0;
}
class B: public A
{
public:
void myFoo();
void hello() { std::cout << "Hello!"; }
}
In class B, I don't want to use A::foo() but only B::myFoo() what should I do?
In such case you either need to provide some dummy implementation for the pure virtual function or review again your design... probably you should not inherit from A.
Similar thing is in your case. Probably your class C should not inherit from class B.
Just replace your single line as below.
Derived C only from A.
Your code
struct C : public B,public A{
using A::foo;
};
Replace above code with below code,
struct C : public A{
using A::foo;
};
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.