I have a problem that I have not yet tested/compiled and wondering if it is possible and if it is bad design?
My Problem:
I want to have an abstract base class A and a abstract derived class B.
I realize if this is possible I will have a number of pure virtual member functions in each class and also I will not be able to initialize these objects, but that is a given for abstract classes.
In my design I will have another derived class C which I would then initialize - class C would be derived from class B.
I would have something that looked like this
class C
^
|
abstract class B
^
|
abstract base class A
My Question:
Is this possible first of all? I would suspect so, but not declaring the pure virtual functions in A in class B may be troublesome?
e.x.
class A {
public:
virtual void test()=0;
};
class B: public A {
public:
virtual void test()=0;
virtual void anotherTest()=0;
};
Is the above okay?
Is this bad c++ design? In future I will have derived classes from A so it would be nice to have this design.
Nothing wrong with it, and it will certainly work. Example follows
stefanos-imac:dftb borini$ more test.cpp
#include <iostream>
class A {
public:
A(void) { std::cout << "A" << std::endl; }
virtual void method1() = 0;
};
class B : public A {
public:
B(void) : A() { std::cout << "B" << std::endl; }
virtual void method2() = 0;
};
class C : public B {
public:
C(void) : B() { std::cout << "C" << std::endl; }
virtual void method1() { std::cout << "method1" << std::endl; }
virtual void method2() {std::cout << "method2" << std::endl; }
};
int main() {
C c;
c.method1();
c.method2();
}
stefanos-imac:dftb borini$ ./a.out
A
B
C
method1
method2
Thank you for reminding me that I can still type basic C++.
Related
I am learning C++ and I am confused about the multiple inheritance and the interface classes.
I want to have a class that inherits from several others. Also, I want to use that derived class through an interface. So I suppose, the derived class should extend the base classes, and the derived interface should extend the base interfaces. I would have done that in other languages, but I think C++ does not work like that.
This is the code I thought should work:
#include <iostream>
using std::cout;
using std::endl;
class
Base1Itf
{
public:
virtual void blue() = 0;
};
class
Base1Abs
:
public Base1Itf
{
public:
void blue()
{
cout << "blue" << endl;
}
};
class
DerivedItf
:
public Base1Itf
{
public:
virtual void red() = 0;
};
class
Derived
:
public Base1Abs,
public DerivedItf
{
public:
void red()
{
cout << "red" << endl;
}
};
int main()
{
DerivedItf* d = new Derived();
d->red();
d->blue();
delete d;
return 0;
}
This is the compiler error I get:
src/test.cpp: In function ‘int main()’:
src/test.cpp:49:30: error: invalid new-expression of abstract class type ‘Derived’
DerivedItf* d = new Derived();
^
src/test.cpp:35:2: note: because the following virtual functions are pure within ‘Derived’:
Derived
^~~~~~~
src/test.cpp:10:16: note: virtual void Base1Itf::blue()
virtual void blue() = 0;
^~~~
In the example only a base class is implemented, but there will be many more.
What I am doing wrong? Thank you.
EDIT
If I remove the Base1Abs inheritance of Base1Itf for avoiding the Diamond Problem, the compiler shows the same error.
This is the well known diamond problem in C++. This is how you solve it:
#include <iostream>
using std::cout;
using std::endl;
class Base1Itf {
public:
virtual void blue() = 0;
virtual ~Base1Itf() { }
};
class Base1Abs : virtual public Base1Itf {
public:
void blue() override {
cout << "blue" << endl;
}
virtual ~Base1Abs() { }
};
class DerivedItf : virtual public Base1Itf {
public:
virtual void red() = 0;
virtual ~DerivedItf() { }
};
class Derived : public Base1Abs, public DerivedItf {
public:
void red() override {
cout << "red" << endl;
}
virtual ~Derived() { }
};
int main() {
DerivedItf* d = new Derived();
d->red();
d->blue();
delete d;
return 0;
}
It is also recommended to use virtual destructors in inheritance.
You see, what happens here is that classes Base1Abs and DerivedItf both inherit a copy of blue. Now, when you inherit another class Derived from these 2, that class inherits 2 copies of blue and then the compiler starts wondering which copy is to be called. So, you inherit the 2 classes virtually resulting in only one copy of blue getting inherited
Can I have a virtual function in the base class and some of my derived classes do have that function and some don't have.
class A{
virtual void Dosomething();
};
class B : public A{
void Dosomething();
};
class C : public A{
//Does not have Dosomething() function.
};
From one of my c++ textbook:
Once a function is declared virtual, it remains virtual all the way down the inheritance, even if the function is not explicitly declared virtual when the derived class overrides it.
When the derived class chooses not to override it, it simply inherits its base class's virtual function.
Therefore to your question the answer is No. Class c will use Class A's virtual function.
Derived classes do not have to implement all the virtual functions, unless it is a pure virtual function. Even in this case, it will cause an error only when you try to instantiate the derived class( without implementing the pure virtual function ).
#include <iostream>
class A{
public :
virtual void foo() = 0;
};
class B: public A{
public :
void foo(){ std::cout << "foo" << std::endl;}
};
class C: public A{
void bar();
};
int main() {
//C temp; The compiler will complain only if this is initialized without
// implementing foo in the derived class C
return 0;
}
I think the closest you might get, is to change the access modifier in the derived class, as depicted below.
But, I would consider it bad practice, as it violates Liskov's substitution principle.
If you have a situation like this, you might need to reconsider your class design.
#include <iostream>
class A {
public:
virtual void doSomething() { std::cout << "A" << std::endl; }
};
class B : public A {
public:
void doSomething() override { std::cout << "B" << std::endl; };
};
class C : public A {
private:
void doSomething() override { std::cout << "C" << std::endl; };
};
int main(int argc, char **args) {
A a;
a.doSomething();
B b;
b.doSomething();
C c;
//c.doSomething(); // Not part of the public interface. Violates Liskov's substitution principle.
A* c2 = &c;
c2->doSomething(); // Still possible, even though it is private! But, C::doSomething() is called!
return 0;
}
This question already has answers here:
What's the difference between the Derived class override the base class's virtual function with or not with a "virtual" prefix? [duplicate]
(2 answers)
Closed 5 years ago.
I have three following classes:
class A
{
private:
std::string device;
public:
std::string getDeviceType() { return device; };
void setDeviceType(std::string device) { device = device; };
virtual void doSomething() = 0;
virtual void doSomething2() = 0;
};
class B: public A
{
private:
public:
B(){ ; };
virtual ~B(){ ; };
void doSomething() { std::cout << "I am usual B" << std::endl; };
void virtual doSomething2() { std::cout << "I am usual B" << std::endl; };
};
class C : public B
{
private:
public:
C(){ ; };
~C(){ ; };
void doSomething() { std::cout << "I am C" << std::endl; };
void doSomething2() { std::cout << "I am C" << std::endl; };
};
main:
B *myHandler = new C();
myHandler->doSomething();
myHandler->doSomething2();
but output is not as expected, my expected output was I am usual B and then I am C, because doSomething() is a non virtual member of class B. But the real output was I am C and then I am C. Do you know why?
because of doSomething() is non virtual member of class B
This is where you are mistaken. In A you declare doSomething() as virtual. That means that it is implicitly marked virtual in classes that derive from it. So doSomething() in B is virtual which means you will call C's doSomething().
The reason is that doSomething is marked as virtual in class A. So it remains virtual in classes B and C because they inherit from class A.
As this function is virtual, it is called according to the real type of the object, which is C in your case, and you get the output: I am C.
Once marked virtual, it remains virtual in all derived classes.
In C you overrode both doSomething() and doSomething2(). You instantiate C, so the methods of C are called in both cases.
If you omitted the override in C of doSomething(), the output would be as you expected it.
KR,
Melle
I give the following example to illustrate my question:
class Base
{
public:
virtual void do()=0;
}
class A: public Base
{
public:
void do();
};
class B: public Base
{
public:
void do();
}
class AB: public Base
{
public:
void do()
{
a_.do();
// if not succeed
{
b_.do();
}
}
private:
A a_;
B b_;
}
From the above codes, we can see that class A, B and AB come from the same Base class. class AB, however, needs to invoke both class A and class B. Here is my question: what's the potential problem with the class AB? Are there other alternatives?
One alternative might be:
class Base
{
public:
virtual void do()=0;
}
class A: public Base
{
public:
void do();
};
class B: public Base
{
public:
void do();
}
class AB: public A
{
public:
void do()
{
A::do();
// if not succeed
{
b_.do();
}
}
private:
B b_;
}
I have no idea what you really want to achieve. But if all of your classes should only have one copy of instance data from Base, you need a virtual Base class.
The problem from your first example with AB is, that you have three! times data of class Base. One from inherit Base, one as part of Member B which itself derives from Base and the same from Member A. Is that what you intend?
I give you the following snipped to see how you can work with exact ONE copy of Base in all of your class instances. Maybe that is what you want to get?
I add some data to Base to see how construction works while using virtual base classes. It is important that the base class constructor will not be called from the constructors of directly inherited classes! You need to call the constructor directly from the outermost constructor as shown in class AB constructor!
As a remark: Virtual Base classes should be used only if nothing else fits the design. Often the need of such a solutions shows a design problem. But as always in programming: If this fits exactly your needs, it is technically absolutely ok to do it.
class Base
{
private:
std::string text;
public:
Base( const std::string& str ): text(str) {}
virtual void Do() { std::cout << text << std::endl; }
};
class A: virtual public Base
{
public:
A():Base("Default from A") {}
void FuncA() { std::cout << "FuncA" << std::endl; }
void Do() { std::cout << "Via A" << std::endl; Base::Do();}
};
class B: virtual public Base
{
public:
B(): Base ("Default from B") {}
void FuncB() { std::cout << "FuncB" << std::endl; }
};
class AB: public A,B
{
public:
//Important to know that init of Base MUST be done from here and not from A nor B !!
AB( const std::string &s): Base(s) {}
void Do() { std::cout << "Via AB" << std::endl; Base::Do(); A::Do(); B::Do();}
};
int main()
{
A a;
a.Do();
std::cout << "####" << std::endl;
B b;
b.Do();
std::cout << "####" << std::endl;
AB ab("Hallo");
ab.Do();
std::cout << "####" << std::endl;
}
what's the potential problem with the class AB?
I don't know of any well known problem that would necessarily arise from your design. You should ask yourself "Why would there be a problem?".
Are there other alternatives?
There are many alternatives. For example, neither A nor B contain any state, so you could just as well stop using classes in favor of free functions and replace dynamic binding with a function pointer.
To be able to compare different alternatives, you should first decide what problem you are trying to solve.
You should inherit from A and B and not from Base, because A and B already do so.
I have 1 base class and a couple of derrived classes that are pretty identic to the base. They look kind of like that:
class Base
{
protected:
data stuff;
size_t length;
public:
Base();
~Base();
virtual void print()
{
std::cout << "Base" << std::endl;
}
// Some more virtual functions
};
class Der1: public Base
{
public:
void print()
{
std::cout << "Der1" << std::endl;
Base::print();
}
};
class Der2: public Base
{
public:
void print()
{
std::cout << "Der2" << std::endl;
Base::print();
}
};
This example is kind of stupid, but what I want to say is that derived classes don't really affect the data itself - only 1 method that does something before actually printing data.
The problem I have is that I have some functions that get Base class as a parameter and does something with the data. The problem is - I can pass derived classes to those functions, but they are passes as Base class - so they lose their overloaded print, and if printed from inside of such function - it won't print any "Der1" or "Der2" strings to stdout.
Edit: They are passed as (const Base &source)
So my question is - what is a way to properly pass derived classes to such functions?
It looks like your functions get Base class as the parameter by value. If you use passing by reference instead - so function(Base& object) instead of function(Base object) - nothing will be lost.
In addition to previous answer, please see below your example:
#include <iostream>
class Base
{protected:
int stuff;
size_t length;
public:
Base(){};
~Base(){};
virtual void print()
{std::cout << "Base" << std::endl;}
// Some more virtual functions
};
class Der1: public Base
{public:
Der1(){};
~Der1(){};
void print()
{
std::cout << "Der1" << std::endl;
Base::print();
};
};
class Der2: public Base
{public:
void print()
{
std::cout << "Der2" << std::endl;
Base::print();
};
};
void function(Base& base)
{
base.print();
}
int main(void)
{
Der1 derived;
function(derived);
return 0;
}
Execution:
Der1
Base