Does it important in which order you inheritence abstact classes, which has same functions ?
class A {
public:
virtual void f1() = 0;
virtual void f2() = 0;
};
class B : public A {
public:
virtual void f1() { globalF1_B(); }
virtual void f2() { globalF2_B(); }
};
class C : public A {
public:
virtual void f1() { globalF1_C(); }
};
class D : public A, public B, public C { };
class E : public A, public C, public B { };
Does D and E classes would be the same, if I would write it like below:
class D{
public:
virtual void f1() { globalF1_C(); }
virtual void f2() { globalF2_B(); }
};
class E {
public:
virtual void f1() { globalF1_B(); }
virtual void f2() { globalF2_B(); }
};
PS. I inheritence class A into class D and class E just in case I can forget make some realization of class A's function.
No there are not the same. Besides an invalid C++ code provided, we can say :
In the first case your classes D and E have two method f1() (one inherited from B and one inherited from C) and one method f2() (inherited from C). If you would be able to construct a D object name d, then d.f1() would be reported as an ambiguity that you would need to clarify either this way : d.B::f1() or this one d.C::f1().
While in the second case your classes will only have two methods f1() and f2().
#include <iostream>
using namespace std;
class A {
public:
virtual void f1() = 0;
virtual void f2() = 0;
};
class B : public A {
public:
virtual void f1() { cout << "B::f1()" << endl; }
virtual void f2() { cout << "B::f2()" << endl; }
};
class C : public A {
public:
virtual void f1() { cout << "C::f1()" << endl; }
virtual void f2() { cout << "C::f2()" << endl; }
};
class D : public B, public C { };
class E : public C, public B { };
int main() {
D d;
// d.f1(); // t.cpp:28:5: error: member 'f1' found in multiple base classes of different types
d.C::f1();
d.B::f1();
}
NO, the first version of D & E won't compile either. there would be ambiguity in resolving f1 and f2 in D and E
Related
Consider the following code
class A {
int x, y;
public:
A(){}
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
int a, b, c;
public:
B(){}
};
int main() {
A obja;
B objb;
obja.PrintSize();
objb.PrintSize();
}
The intent of "PrintSize()" is to get the size of the current class where we are calling it from. What happens is that this-keyword refers to class A even though we are calling it from B. We don't want this since we need this function to be general for child classes.
We could obviously redefine the function verbatim to every class. The code would become harder to hande since there's so many unnesessary lines. Not to mention that re-writing the function to every class would defeat the purpose of deriving it in the first place.
Here's my temporary fix:
class A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class C : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class D : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
While the accepted answer may have solved the immediate problem, you suddenly have no common base class for B and C. They inherit from two unrelated classes, namely A<B> and A<C>.
An alternative is to create a common base that defines an interface (called Interface below) and to add the CRTP class template between the derived classes and the interface. This lets you keep pointers and references to Interface and call the virtual member functions using those.
Here's an example of storing pointers to the common base class in a vector:
#include <iostream>
#include <memory>
#include <vector>
struct Interface {
virtual ~Interface() = default;
virtual void PrintSize() const = 0;
virtual void do_stuff() const = 0;
};
template<typename T>
struct Printer : public Interface {
void PrintSize() const override {
std::cout << sizeof(T) << '\n';
}
};
class B : public Printer<B> {
int a{};
public:
void do_stuff() const override { std::cout << "B doing stuff\n"; }
};
class C : public Printer<C> {
int a{}, b{}, c{};
public:
void do_stuff() const override { std::cout << "C doing stuff\n"; }
};
int main() {
std::vector<std::unique_ptr<Interface>> objs;
objs.emplace_back(std::make_unique<B>());
objs.emplace_back(std::make_unique<C>());
for(auto& ptr : objs) {
ptr->do_stuff();
ptr->PrintSize();
}
}
Possible output:
B doing stuff
16
C doing stuff
24
You can use the CRTP idiom to do this.
https://eli.thegreenplace.net/2011/05/17/the-curiously-recurring-template-pattern-in-c
The idea is the parent class is a template, so you can have access to the type of the child class directly in it.
With that, you'll be able to remove all "PrintSize" from child class.
Example :
template <typename Derived>
class A {
int x, y;
public:
A() {}
void PrintSize() { cout << sizeof(Derived) << endl; }
};
class B : public A<B> {
int a, b, c;
public:
B() {}
};
class C : public A<C> {
public:
C() {}
};
int main() {
C objc;
B objb;
objc.PrintSize();
objb.PrintSize();
}
The output is :
8
20
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 have two base classes and a class that inherits both base classes.
Both base classes have a virtual function with the same signature, and I want to provide different implementations in the derived class to each virtual function.
class A{
virtual void f() = 0;
}
class B{
virtual void f() = 0;
}
class Derived:public A, public B{
void A::f() override{ // Error
...
}
void B::f() override{ // Error
...
}
}
What is the correct way to do this? (I cannot rename the virtual function. Actually the two base classes are generated from the same template class.)
template <typename T>
class AShim : public A {
void f() override {
static_cast<T*>(this)->A_f();
}
};
template <typename T>
class BShim : public B {
void f() override {
static_cast<T*>(this)->B_f();
}
};
class Derived: public AShim<Derived>, public BShim<Derived> {
void A_f();
void B_f();
};
class A {
public:
virtual void f() = 0;
};
class B {
public:
virtual void f() = 0;
};
class Derived :public A, public B {
public:
void A::f() {
cout << "Inside A's version"<<endl;
}
void B::f() {
cout << "Inside B's version"<<endl;
}
};
int main()
{
Derived derived;
cout << "calling A" << endl;
A *a;
a = &derived;
a->f();
cout << "calling B" << endl;
B *b;
b = &derived;
b->f();
}
Works fine for me. No need to explicitly mention override keyword as pure virtual functions will be overridden by virtue of its default properties.Use base class's scope while defining the functions as you have already done. Use public access specifier to enable derived classes to override the pure virtual function. That's all.
I am aware of the statement,
"A virtual function of a replicated base class can be overridden by a (single) function in a derived class."
I am curious to know if it is possible to provide more than one definition, in case it is possible—how to define and invoke properly?
Just to make it more clear,
My classes and class hierarchy would be like
A A
| |
B C
\ /
D
//i.e., I am not deriving B and C from a virtual base A.
class A {
virtual void f(){
cout<<"belongs to A"<<endl;
}
}
class B: public A {
void f(){
cout<<"belongs to B"<<endl;
}
}
class C: public A {
void f(){
cout<<"belongs to C"<<endl;
}
}
class D: public B, public C {
void f(){ //This overrides definitions B::f() and C::f()
cout<<"belongs to D"<<endl;
}
}
B* b;
C* c;
D d;
b = &d;
c = &d;
b->f();//This would output "belongs to D"
c->f();//This also would output "belongs to D"
//Now I want to redefine f() in D like this
class D: public B, public C {
void B::f() {
cout<<"belongs to D::B::f()"<<endl;
}
void C::f() {
cout<<"belongs to D::C::f()"<<endl;
}
}
//So that
B* b;
C* c;
D d;
b = &d;
c = &d;
b->f();//This would output "belongs to D::B::f()"
c->f();//This also would output "belongs to D::C::f()"
At some point, you need to be able to tell the compiler which implementation you want to use.
One way to do so this way :
A
/ \
B C
\ /
D
struct A
{
virtual void f();
};
struct B : public A
{
void f() override;
};
struct C : public A
{
void f() override;
};
struct D : public B,C
{
};
int test(int num) {
D d;
d.f(); // undefined
d.A::f(); // Impossible because conversion from D to A is ambiguous
d.B::f(); // calls B implementation
d.C::f(); // calls C implementation
}
Well, here is a basic example of virtual functions
class Person
{
int age;
public:
Person(int=0);
virtual void describe() = 0;
int getAge();
};
Person :: Person(int age)
{
this->age = age;
}
int Person :: getAge()
{
return this->age;
}
class Student : public Person
{
public:
Student(int=0);
void describe();
};
Student :: Student(int age) : Person(age) {}
void Student :: describe()
{
std::cout << "Hi, I am a student, ";
std::cout << this->getAge() << " years old!";
}
class Employee : public Student
{
public:
Employee(int=0);
void describe();
};
Employee :: Employee(int age) : Person(age) {}
void Employee :: describe()
{
std::cout << "Hi, I am an employee, ";
std::cout << this->getAge() << " years old!";
}
Short answer is NO. – curiousguy
Answer provided by #curiousguy in comments.
I have the following classes, and I'm trying to access a base member using an object of class H, and I get an H::a is ambiguous warning.
class E {
public:
E() : a(11) { }
int a;
};
class F : public E {
public:
F() : b(22) { }
int b;
};
class G : public E {
public:
G() : c(33) { }
int c;
};
class H: public F, public G {
public:
H() : d(44) { }
int d;
};
I tried making the data member a static, but then it doesn't let me initialize it in the base constructor. What's a solution to these two problems?
Class "H" has two variables called "a", one derived from F and one from G. You can either use a qualifier,
H::a
or you can use the "virtual" inheritance specifier (see https://stackoverflow.com/a/419999/257645)
#include <iostream>
struct A {
int a;
};
struct B : virtual public A {
};
struct C : virtual public A {
};
struct D : virtual public B, virtual public C {
void d1() { a = 1; }
void d2() { a = 2; }
};
int main() {
D d;
d.d1();
d.d2();
std::cout << d.a << std::endl;
}
http://ideone.com/p3LPe0