Suppose I have class parent and the inherited classes are child1, child2, and child3. All inherit the function TellName of parent. I want to know if there is any way to call the class parent's TellName function and automatically run all functions of child1, child2, and child3.
visualization:
class parent
{
public:
virtual void TellName() { }
};
class child1 : public parent
{
public:
void TellName() override { std::cout<<"Child1"<<"\n"; }
};
class child2 : public parent
{
public:
void TellName() override { std::cout<<"Child2"<<"\n"; }
};
class child3 : public parent
{
public:
void TellName() override { std::cout<<"Child3"<<"\n"; }
};
Now I want to run the TellName function of parent and get output as:
>> Child1
>> Child2
>> Child3
I am assuming that it is possible by using the VTable of the function TellName. Hope my question is clear.
The only standard way to do what you are trying to do using virtual functions is to instantatiate objects of all types and call TellName() function on them. I.e. something like this:
int main()
{
child1 c1;
child2 c2;
child3 c3;
c1.TellName();
c2.TellName();
c3.TellName();
}
Or, since you made TellName() function virtual, you can put all these objects in one container and print names by calling TellName() from parent's pointer. Something like this:
int main()
{
std::vector<std::unique_ptr<parent>> vec;
vec.push_back(std::make_unique<child1>());
vec.push_back(std::make_unique<child2>());
vec.push_back(std::make_unique<child3>());
for (auto& ptr : vec) {
ptr->TellName();
}
}
BUT, if you want to print these names without instantiation of child objects, then you don't need and shouldn't use virtual functions. Instead you can use static functions.
Related
I have something along the lines of
class A {
public:
class subA {
public:
// some variables
};
std::vector<subA> children;
void foo() {
// modify children
}
};
class B : public A {
public:
class subB : public A::subA {
public:
// some extra variables
}
std::vector<subB> children;
}
B b;
b.foo();
foo() only uses base attributes of subA. Is there anyway I can have B.foo() use the children composed of subB instead of the children of subA?
Since A is not aware of subB, does this mean I have to make foo virtual and rewrite the same code so it uses the correct children vector (composed of subB)? Any better way to do this?
I learnt the work of virtual functions: if the inherited classes inherit a function from the base class, and it is custom for each ones, I can call these functions with pointers that point to the base class, this way:
BaseClass* PointerName = &InheritedClassObject;
But what about variables? I found this question on the site that tells: I can't create virtual variables in C++. My experience proves it: for variables, Visual C++ says: 'virtual' is not allowed.
Then, what is the way to reach the value of a(n inherited) variable that belongs to an inherited class by using base class pointers?
Based off your comment, I think what you are trying to ask if how do child classes access their parent's variables. Consider this example:
class Parent
{
public:
Parent(): x(0) {}
virtual ~Parent() {}
protected:
int x;
};
class Child: public Parent
{
public:
Child(): Parent(), num(0) {}
private:
int num;
};
void Child::foo()
{
num = x; //Gets Parent's x,
}
NB: If you define an x in Child, that masks the x in Parent. So, if you want to get the x in Parent, you would need: Parent::x. To simply get x from a Child c, you use c.x if x is public or use a getter if x is protected or private:
int Child::getNum()
{
return num;
}
You don't. Virtual functions use them, do whatever needs to be done and return result if needed.
You can't use any function, data member of an inherited class if it's casted back to base class. However, you can alter those variables with virtual functions. Example:
#include <iostream>
class BaseClass {
public:
BaseClass() {}
virtual void do_smth() = 0;
private:
};
class InheritedClass: public BaseClass {
public:
InheritedClass(): a(1) {}
virtual void do_smth() { std::cout << ++a << std::endl; }
private:
int a;
};
int main() {
BaseClass* ptr = new InheritedClass();
ptr->do_smth();
return 0;
}
In this piece of code, virtual function did alteration of variable belongs to InheritedClass.
I have the following code:
class Interface
{
virtual void method()=0;
};
class Base : public Interface
{
virtual void method()
{
//implementation here
}
};
class Parent: public Interface
{
};
class Child : public Base, public Parent
{
};
int main()
{
Child c;//ERROR: cannot instantiate abstract class
}
Now I know why this is happening, since I'm inheriting Parent then I have to implement method again. But it's already defined in Base class and I don't want to override that definition for every child class. I think there was some standard way of getting rid of this in c++ (telling compiler which copy of Interface should it use) I just can't remember what it was.
What you are talking about is called dominance.
From the linked article:
class Parent
{
public:
virtual void function();
};
class Child1 : public virtual Parent
{
public:
void function();
};
class Child2 : public virtual Parent
{
};
class Grandchild : public Child1, public Child2
{
public:
Grandchild()
{
function();
}
};
You have a diamond-shaped hierarchy but are not using virtual inheritance.
As a result, you end up with two distinct virtual method() functions in your Child class.
One way to fix it is to move to using virtual inheritance. This way you'll only have a single Child::method() and won't need two implementations.
Pure virtual functions must be defined in the derived class.
If you don't do so, your derived class (in this case "child") will itself become an abstract class which can't be instantiated and hence the error.
I have 6 classes which all perform the same actions. I would like to move common behavior to a common [base] class.
There are actions to be performed on 6 separate objects. The six objects are located in derived classes. Intuitively, the private member objects would be accessed through the child (derived class) in the base class.
What is the C++ pattern I am looking for?
class Base
{
// Common behavior, operate on m_object
...
void Foo()
{
m_object.Bar();
}
};
class Derived1 : public Base
{
// No methods, use Base methods
private:
MyObject1 m_object;
}
class Derived2 : public Base
{
// No methods, use Base methods
private:
MyObject2 m_object;
}
The thing that is boxing me into this situation is MyObject1, MyObject2, etc offer Bar(), but don't share a common base class. I really can't fix the derivation because the objects come from an external library.
If they are introduced in the derived classes, then the base class cannot directly access them. How would the base class know that all derived classes have a specific member?
You could use virtual protected methods like so:
class my_base
{
protected:
virtual int get_whatever();
virtual double get_whatever2();
private:
void process()
{
int y = get_whatever();
double x = get_whatever2();
//yay, profit?
}
}
class my_derived_1 : my_base
{
protected:
virtual int get_whatever()
{
return _my_integer;
}
virtual double get_whatever2()
{
return _my_double;
}
}
Another possibility (if you want to call the base methods from the derived classes) is to simply supply the arguments to the base methods.
class my_base
{
protected:
void handle_whatever(int & arg);
};
class my_derived : my_base
{
void do()
{
my_base::handle_whatever(member);
}
int member;
};
C++ does and doesn't. It has a very powerful multiple inheritance support, so there is no super keyword. Why? Imagine that your base class is, say, inherited by another two classes, or even is a part of virtual inheritance hierarchy. In that case you can't really tell what super is supposed to mean. On the other hand, there are virtual methods, you can always have them in base class and implement in derived classes (that's what languages like Java do, except that they they don't have multiple class inheritance support). If you don't want to go with polymorphism, you can use something like this:
#include <cstdio>
template <typename T>
struct Base
{
void foo ()
{
std::printf ("Base::foo\n");
static_cast<T *> (this)->bar ();
}
};
struct Derived : Base<Derived>
{
void bar ()
{
std::printf ("Derived::bar\n");
}
};
int
main ()
{
Derived d;
d.foo ();
}
This is an extremely simple example - you can extend the above example with access control, friends, compile-time assertions etcetera, but you get the idea.
Have you considered not using inheritance?
class FooBar
{
MyObject m_object;
public:
FooBar(MyObject m): m_object(m) {}
//operate on different m_objects all you want
};
What about deriving your six separate objects from a common base class? Then you can declare virtual methods in that base class to create your interface, and then implement them in the derived object classes.
Maybe you just need a template instead of superclass and 6 derived classes?
It seems that you need to access not the parent's, but child's field. You should do it by introducing an abstract method:
class ParentClass
{
public:
void f();
protected:
virtual int getSomething() = 0;
};
ParentClass::f()
{
cout << getSomething() << endl;
}
class DerivedClass : public ParentClass
{
protected:
virtual int getSomething();
}
DerivedClass::getSomething() { return 42; }
If you need to access parent's method, just use ParentClass::method(...):
class ParentClass
{
public:
virtual void f();
};
class DerivedClass : public ParentClass
{
public:
virtual void f();
};
void DerivedClass::f()
{
ParentClass::f();
}
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; }
}