Let's see the following C++ codes.
Each inherited class has its member variables and initialization function.
These member variables are some different(almost same type) between inherited classes.
Is there any good way to move (or merge) this initialization into base class?
class Base {
public:
virtual init() = 0;
}
class A: public Base {
public:
int a1;
void init() { a1 = 0;}
}
class B: public Base {
public:
int b1;
void init() { b1 = 1;}
}
No. Base has no knowledge of A::a1 or B::b1. More importantly it should not have any knowledge of it's subclass members as this leads to a fundamental breakdown of the encapsulation you're trying to achieve in the first place.
The best you can do is have your Base class define a virtual method for initialisation and control when that method is called. It is up to each subclass to override the method and ensure that when initialisation is needed it is performed according to each subclass's respective requirements.
One thing to note is that if your initialisation is intended to be once-off for the lifetime of each object, the the correct place to do this is using constructors as per koizyd's answer.
On a related note, I'd like to point out that what you're asking is a variation on one of the most common OO design flaws I've seen in my career.
Using inheritance for code reuse not encapsulation.
Basically you're trying to push functionality into the base class (for reuse), and all this really achieves is making the Base class large, top-heavy and unmaintainable.
In C++ we can't (almost always) create function init, we use constructors
e.g
class Base {
};
class A : public Base {
public:
int a1;
A():Base(), a1(0) {}
};
class B : public Base {
public:
int b1;
B():Base(), b1(1){}
};
Construct "child" is A():Base(),a1(0), it's initializer list (:Base(),a1(0)), which create Base object, and int b1.
You should remember about ; after class.
I'd probably structure code like this:
class Base {
public:
void init() { sub_init(); }
protected:
virtual void sub_init() = 0;
}
class A: public Base {
public:
int a1;
protected:
void sub_init() { a1 = 0;}
}
class B: public Base {
public:
int b1;
protected:
void sub_init() { b1 = 1;}
}
The alternative of doing something like (syntax probably not correct...):
class Base {
public:
virtual void init() = 0;
protected:
void generic_init<T>(T &foo, T const &bar) { foo = bar; }
}
class A: public Base {
public:
int a1;
void init() { generic_init<int>(a1, 0); }
}
class B: public Base {
public:
int b1;
void init() { generic_init<int>(b1, 1); }
}
Looks awful to me!
Maybe you could use the template class skills to solve the problem. Like:
template <typename T> class Base {
public :
virtual void init( T t ) = 0;
};
class A: public Base<T> {
public:
T a1;
void init( T t ) { a1 = t;}
}
class B: public Base<T> {
public:
T b1;
void init( T t ) { b1 = t;}
}
You could have a try.
Related
how to make derived classes access the member data and functions of each other. both classes are inherited from base class as pure abstract.
here my scenario
class Base
{
public:
virtual void do_something() = 0;
};
class Derived1 : public Base
{
public:
virtual void do_something()
{
// need to use a2
// need to use func
}
private:
int a1;
};
class Derived2 : public Base
{
public:
virtual void do_something()
{
// need to use a1
}
void func(){}
private:
int a2;
};
Probably you need to re-think your design. There will be no memory allocated to a1 for Derived2's object and similarly for a2 and Derived1. What you are asking is equivalent to saying, both cat and dog are animals, I want to use cat::whiskers in dog.
You probably need this:
class Base
{
public:
virtual void do_something() = 0;
};
class Derived : public Base
{
public:
int a1;
int a2;
void func(){}
};
class Derived1 : public Derived
{
public:
virtual void do_something()
{
// can use a2 and func here
}
};
class Derived2 : public Derived
{
public:
virtual void do_something()
{
// need to use a1
}
void func() override {}
};
I've posted about this problem before (Here), this is a different approach to a solution. This solution to be seems to better encapsulate the behavior for those implementing the class, since it prevents them from needing to explicitly up cast.
Here's the problem:
I have a project in which I want to isolate core behavior in most objects, while providing additional behavior through derived objects. Simple enough:
class BaseA
{
virtual void something() {}
}
class DerivedA : public BaseA
{
void something() {}
void somethingElse() {}
}
Now let’s say I also have a second set of classes, same inheritance scheme except that they aggregate the above classes. However, I would like the base version to use the base class, and the derived version in the derived class. My solution i was thinking about 'hiding' the base class variable by using the same name;
class BaseB
{
BaseA *var;
BaseB()
{
var = new BaseA();
}
virtual void anotherThing1();
virtual void anotherThing2();
virtual void anotherThing3();
}
class DerivedB : public BaseB
{
DerivedA *var;
DerivedB()
{
var = new DerivedA();
}
void anotherThing1();
void anotherThing2();
void anotherThing3();
void andAnother1();
void andAnother2();
}
The goal for this approach is so that functions that rely on the derived aggregated class no longer need to explicitly cast to achieve the gained functionality.
void func1( BaseB &b )
{
b.anotherThing1();
b.var->something();
}
void func2( DerivedB &b )
{
b.anotherThing1();
b.andAnother1();
b.var->something();
b.var->somethingElse();
}
void main( int argc, char **argv )
{
BaseB baseB;
DerivedB derivedB;
func1( baseB );
func1( derivedB );
func2( derivedB );
}
Would this be considered bad practice?
Would this be considered bad practice?
Yes, it would be bad practice, because the var in the Base would be unused. It does not look like DerivedB should be deriving from BaseB: instead, they should be derived from the same abstract base class, like this:
class AbstractB {
public:
virtual void anotherThing1() = 0;
virtual void anotherThing2() = 0;
virtual void anotherThing3() = 0;
};
class DerivedB1 : public AbstractB { // Former BaseB
BaseA *var;
public:
DerivedB1() {
var = new BaseA();
}
virtual void anotherThing1();
virtual void anotherThing2();
virtual void anotherThing3();
};
class DerivedB2 : public AbstractB { // Former DerivedB
DerivedA *var;
public:
DerivedB2() {
var = new DerivedA();
}
void anotherThing1();
void anotherThing2();
void anotherThing3();
void andAnother1();
void andAnother2();
};
General principle in use here is that you should try making all your non-leaf classes in your inheritance hierarchy abstract.
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 trouble when designing classes like this
class C1 {
public:
void foo();
}
class C2 {
public:
void foo();
}
C1 and C2 has the same method foo(),
class Derived1 : public Base {
public:
void Update() {
member.foo();
}
private:
C1 member;
}
class Derived2 : public Base {
public:
void Update() {
member.foo();
}
private:
C2 member;
}
Update() of both Derived class are exactly the same, but the type of member is different.
So i have to copy the Update implement for every new derived class.
Is that a way to reduce this code duplication? I only come out with a solution with macro.
I think there is a more elegant way to solve this with template but I can not figure it out..
EDIT:
thanks a lot guys but i think i missed something..
1.I'm using c++
2.In reality each Derived class has about 5 members, they all afford the foo() method and are derived from the same base class. My situation is that i have already written a (very long) Update() method and it can work for every derived class without any modification. So i just copy and paste this Update() to every new class's Update() and this lead to terrible code duplication. I wonder if there is a way in which i need not to rewrite the Update() too much and can reduce the duplication.
thx again
This is exactly the sort of application that class templates are designed for. They allow functions within a class to operate on different data types, without the need to copy algorithms and logic.
This Wikipedia page will give you a good overview of templates in programming.
Here's the basic idea to get you started:
template <class T>
class CTemplateBase
{
public:
void Update()
{
member.foo();
}
private:
T member; // Generic type
}
class CDerived1 : public CTemplateBase<C1>
{
// No common algorithms required here
}
class CDerived2 : public CTemplateBase<C2>
{
// No common algorithms required here
}
If you have the control over C1 and C2, you can either define a base class or an abstract base class and handle it at Base class or third helper class.
If your Drived1 and Derived2 are same except for the type (C1 and C2) of member, then you can consider using a single class Derived and a template.
(Excuse my syntax if incorrect, i m C# dev :D )
template <class T>
class Derived : public Base {
public:
void Update() {
member.foo();
}
private:
T member;
}
Something on the above lines.
Move the method to the parent class:
class IFooable {
public:
virtual void foo() = 0;
}
class C1 : IFooable {
public:
void foo();
}
class C2 : IFooable {
public:
void foo();
}
class Base {
public:
void Update() {
member->foo();
}
private:
IFooable* member
}
class Derived1 : public Base {
Derived1 () : member(new C1()) {}
~Derived1 () { delete member; }
}
class Derived2 : public Base {
Derived2 () : member(new C2()) {}
~Derived2 () { delete member; }
}