Call to base class method: accessing member of derived class - c++

Say we have two classes:
class Parent
{
public:
vector<int> x;
protected:
void Method();
}
and
class Child : public Parent
{
public:
vector<double> x;
}
and the method Method() operates on x and makes some operation, which is compatible for both types int and double:
void Parent::Method()
{
x.push_back(1);
}
Then, if I will create an instance of Child class, initialize vector<double> x, and then call derived method Method() from the base class, C++ will try to operate on Parent's member x and not the Child's one. Is there any way how to make base class method to automatically operate on the member that belongs to created class, Child's vector<int> x?
EDIT:
As McAden correctly noted, this behavior can be easily achieved using polymorphism: three classes - 1 base and 2 derived. But does it mean that it is impossible with just 2 classes?

Since you only want to create instances of Child and you want the Child to dictate the type of the vector, this problem is more naturally solved with a template Parent. As a simple example, Parent could be parameterized by what vector<> should contain:
template <typename T>
class Parent {
public:
std::vector<T> x;
protected:
void Method () { x.push_back(1); }
};
class Child : public Parent<double> {
//...
};
If you actually have many such things you want the child to control in the Parent, then you probably should treat Child more like a traits class for the Parent. Thus, Parent would actually be parameterized by its Child, and your code would then be using CRTP. which provides "static polymorphism".
template <typename CHILD>
class Parent {
protected:
void Method () {
CHILD *child = static_cast<CHILD *>(this);
child->x.push_back(1);
}
};
class Child : public Parent<Child> {
public:
std::vector<double> x;
};

Changing data types in dealing with inheritance isn't so much possible with the exception being cases where covariance is used. If you want to make a class that handles differing data types what you're probably looking for is a template class:
http://www.learncpp.com/cpp-tutorial/143-template-classes/

Related

Allow descendant to call overridden protected function on instance of another descendant

Suppose we have a base class Base with a public interface, and some protected methods that are used to support the public interface. Simplified example:
class Base {
protected:
virtual int helper() const = 0;
public:
virtual void do_work() {
//By default, just call the helper. Descendants can customize behaviour.
int x = helper();
do_something_with_an_int(x);
}
};
And suppose we have some descendants DerivedA, DerivedB, DerivedC ... that implement this interface.
The reason I want to split up the work in two functions (rather than just use do_work to do everything) is because I want to have a special descendant that might look something like this:
class DescendantWrapper : Base {
Base *impl;
int x;
protected:
int helper() const override {
x += impl->helper();
}
public:
void do_work() override {
helper();
if(some_internal_condition()) {
do_some_other_thing_with_an_int(x);
} else {
x = 0;
}
}
};
The intention is to allow DescendantWrapper to wrap any descendant of Base, and take the place of that descendant in some other code. Of course, the other code would not be aware that its descendant of Base has been wrapped.
The problem is that a derived class (in this example, DescendantWrapper) cannot call a protected method on an instance of its parent class (in this example, Base::helper()).
One solution is to specifically declare DescendantWrapper as a friend of Base. However, this means that other users of this code couldn't create their own descendant wrappers. Does anyone know an alternative to friend functions in this scenario?

Are C++ nested classes the right approach for encapsulation?

I have a global class TRK that has many members and methods. I wanted to organize these by sorting them into different named categories, e.g. Fitting, such that the namespace of the main class isn't overcrowded. In a perfect world, I would want this example to work:
class TRK
{
public:
// constructors
TRK(...);
...
TRK();
~TRK();
// nested classes
class Fitting;
// and many other methods...
private:
...
};
class TRK::Fitting
{
public:
// constructors/destructor
TRK& trk;
Fitting();
~Fitting();
// and many other methods...
private:
...
};
The key thing here that I need is to be able to:
Instance some TRK object using one of the TRK class' constructors, and I need the TRK constructors to be able to also automatically instantiate accompanying nested classes e.g. Fitting, for that instance of TRK. I then need to be able to instantiate/give values to members of these nested classes, within the TRK constructors. For example, if Fitting has some member x, I need to be able to initialize the value for x for that instance of TRK within the TRK constructor, given the arguments to the constructor. What I'm unclear on is how exactly to go about this; how and where can I instantiate these nested classes?
Access members of the nested classes from TRK instances and methods, and vice versa. I already can do the latter by passing TRK by reference to the nest classes, as shown, but I'm not sure how to do the former.
For example, I have methods of Fitting that need to use members of whatever TRK instance that that instance of Fitting was created within. Similarly, I have methods of Fitting that methods of TRK need to be able to call.
Should I even be using nested classes for this? I tried using namespaces and inheritance but I couldn't get things to work the way that I wanted. My core issue here is attempting
Constructing instances of nested classes
If you want the constructor of TRK to in turn cause the construction of a TRK::Fitting variable, the definition of TRK::Fitting must be completely known to it, a forward declaration is not enough. However, once you do that, you can intialize member variables of the nested class type just like you would always do. Here is an example:
class TRK {
class Fitting {
int x;
public:
Fitting(int x): x(x) {}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
};
Having nested classes access the parent class
A nested class is just a regular class, only its name is nested. It does not automatically know where the non-static member variables of the parent are. A simple solution is to provide the nested class with a reference to the instance of the parent class, like so:
class TRK {
class Fitting {
TRK &parent;
int x;
public:
Fitting(TRK &parent, int x): parent(parent), x(x) {}
void foo() {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(*this, y) {}
void bar() {}
};
Another option is to not store a reference to the parent in the child class, but rather to explicitly pass a reference to the parent to every member function of the child class:
class TRK {
class Fitting {
void foo(TRK &parent) {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
void bar() {}
void quux() {
fitting.bar(*this);
}
};
Calling a member function of the child class from the parent class is easy, as shown in TRK::quux().
If you want to use inheritance and have the base class be able to call functions in the derived class, then the curiously recurring template pattern can be used, like so:
template <typename Derived>
class TRK {
...
void bar() {}
void quux() {
// We need to static_cast<> ourself to get an object of type Derived
static_cast<Derived>(*this)::foo();
}
};
class Derived: TRK<Derived> {
...
void foo() {
// We can directly call any base class member functions here
bar();
}
}

How to construct a class with an existing base class pointer?

I have one base class and two derived child's (different classes).
I would like to construct one child and then construct a second child which uses the same base class instance like the first child.
In pseudo code this would look like this:
class Parent
{
public:
int x;
};
class ChildA : public Parent
{
void setX() {x=5;}
};
class ChildB : public Parent
{
int getX() {return x;} //Shall return 5 after calling the set method of ChildA first
};
//Creating instances
ChildA* a;
a = new ChildA();
Parent* ptrToBaseClass = a;
ChildB* b;
b = new ChildB(); //How can I set this to the same base class ptr (Parent*) which instance “a” has?
How can this be achieved with passing the base class pointer?
I would like to construct one child and then construct a second child which uses the same base class instance like the first child.
What you would like is not possible. Each base class sub object is stored within the most derived object.
You can use the existing base to copy initialise the base of another object, but they will be separate.
What you could do to achieve something similar, is to use indirection:
struct Parent
{
std::shared_ptr<int> x = std::make_shared<int>();
};
struct ChildA : Parent
{
void setX() {*x=5;}
};
struct ChildB : Parent
{
int getX() {return *x;} //Shall return 5 after calling the set method of ChildA first
};
int main() {
ChildA a;
Parent& a_base = a;
ChildB b {a_base}; // note that the base is copied here
a.setX();
std::cout << b.getX();
}
This way even though the base objects are separate, they both refer to shared state.
A simpler solution is to store the state in static storage (such as static member, as suggested by Ahmet). But this will make the state shared across all instances while the indirection allows exact control over which objects share which state.
You can make the x in Parent class static. This will allow you to do this - although I have to warn you that this is quite a dodgy code and can bite you in the a**.
Of course, then you have to access it with rather than just x; as Parent::x.
EDIT: I seem to got it wrong. If you want the whole base class as 'shared' rather than just x; you need pointers and custom logic to manage it - there is no direct language construct.

Need help restructuring and/or refacoring this c++ code concerning inheritance between multiple classes

OK, Not sure on the terminology for what I'm trying to do so edits are very welcome.
I've got code such as this:
class CBaseItemTracker
{
public:
CBaseItemTracker();
void IncrementCount() { ++count; }
protected:
int count;
};
class CDerivedItemTracker : CBaseItemTracker
{
public:
CDerivedItemTracker();
void Print() { printf("something:%d\ncount:%d\n", something, count); }
private:
int something;
};
class CBaseClass
{
public:
BaseClass();
private:
CItemTracker item;
};
class CDerivedClass : CBaseClass
{
public:
CDerivedClass();
CDerivedItemTracker GetDerivedItem();
private:
CDerivedItemTracker derived_item;
};
What I would like to accomplish is that CBaseClass::item and CDerivedClass::derived_item are actually the same object such that:
Code within CBaseClass can update item
Code within CDerivedClass can update derived_item (and therby also update item)
Code external to CDerivedClass can retrieve a CDerivedItemTracker object that includes the item variable.
I feel like I am trying to do something that is fundamentally wrong but I'm not seeing a good way to resolve it.
Your goal is that code within CBaseClass can update base member item and
code within CDerivedClass can update members derived_item as well as item.
Is it a member access problem ?
The first two constraints are the basics of inhertance.
The only problem in your code is that you have item member as private. This means that the derived classes won't have access to it. Just change it to be protected instead:
class CBaseClass
{
public:
BaseClass();
protected: //<===== derived classes will have direct acess to this member
CItemTracker item;
};
class CDerivedClass : CBaseClass
{
public:
CDerivedClass();
CDerivedItemTracker GetDerivedItem();
private: // you can leave it private, but if further dirved classe need access
// make it protected as well, but then you should consider public inheritance
// so that the further derived also see the item.
CDerivedItemTracker derived_item;
};
Now the derived class sees both itmes. In GetDerivedItem() you can choose which item to return. But item and derived_item will remain unrelated, as your class definitions define two distinct members.
Or is it about sharing a single (derived) item ?
The third requirement makes the things a little bit more complex. I'm not 100% sure of your intentions. But if the intention is to extend in a derived class an item of the base class, this wont be possible as such, due to C++ standard constraints on the object layout.
Fortunately there are two main alternatives: templates or dynamic member.
Template approach
The template approach should be considered if at compile time you do already make the choice of the member type.
template <class myitem>
class CBase
{
public:
CBase() {}
protected:
myitem item;
};
template <class myitem>
class CDerived : CBase<myitem>
{
public:
CDerived() {}
myitem GetDerivedItem() { return item; }
};
You can use this as follows:
CBase<CBaseItem> b;
CDerived<CDerivedItem> d;
d.GetDerivedItem().Print();
The principle is that for object d in CBase would have a CDerivedItem item, even if you would only access to the subset of its public CBaseItem members.
Dynamic approach
The dynamic approach doesn't use templates, but creates the item during the construction.
Here I present a simple implementation based on references, taking the luxury of some unused members. A more space efficient pointer based variant with dynamic allocation of the item should be prefered whenever space is critical.
class CBase
{
public:
CBase() : item(base_item) {} // when lonesome object: uses its own item
protected:
CBase(CBaseItem &itm) : item(itm) {} // when subovject of a derived class
CBaseItem &item;
private:
CBaseItem base_item; // used only for non derived CBase object.
};
class CDerived : CBase
{
public:
CDerived() : CBase(derived_item) {} // Tell the base class that there's already an item to be used.
CDerivedItem GetDerivedItem() { return derived_item; }
// we can use item as well: it'll be the CBaseItem subobject of derived_item
private:
CDerivedItem derived_item;
};
ATTENTION: for this to work you need public inhertance between item classes ( class CDerivedItem : public CBaseItem)
The difficulty here, is that base classes are constructed first. So you have to provide to the base class constructor the item reference that it has to use. If inadvertently you'd forget, the base would think it is a free object and will use a separate item. THis is why I'd suggest to use the template approach if possible.

Constructor of a subclass of a template-instantiated abstract base class - alternative design patterns required

I have a template like this:
template<typename T>
struct foo {
foo(T t) {
//code
}
virtual double computation() = 0;
//other members
};
I want users to provide their own subclasses with a custom T and computation() like this:
struct my_foo : public foo<std::string> {
double computation() override { return 9.99; }
};
The problem is that this doesn't work:
my_foo("hello");
I would have to ask users to create a new constructor for every subclass, even if all it does is call the superclass constructor. This looks silly.
Can you suggest alternative "design patterns" that may be more suitable for me?
I believe it has no direct relationship with template.
It is simply due to: in C++, constructor is not inherited.
Try this example and you will see it does not work:
class Parent {
public:
Parent(int i) {
cout << "i " << i << endl;
};
};
class Child : public Parent {
};
int main(int argc, char** args) {
Child child(1);
return 0;
}
because by default, constructor of Child will call Parent's no-arg ctor. However no-arg ctor is not available in Parent.
Change Child to provide proper ctor will solve the problem:
class Child : public Parent {
public:
Child(int i):Parent(i) {
}
};
In this example, I created a ctor for Child which takes 1 param. This Child ctor will invoke Parent's Parent(int) ctor.
In your question, you said it is silly to ask Child classes to create the ctor: It is not silly at all! You will never know how the child wants its class to be instantiated. Certain child class may only be reasonable to be constructed with 2 parameters for ctor base on its semantic meaning.
If you really really want it to be done magically, one simplest way you can do is to create macros to "generate" the class declaration and corresponding ctor for the child class. However it is seldom meaningful to do so.
As far as I can see from your example, you want the user to specify a type and a computation function. Since you did not provide a virtual destructor, I assume that you don not want to use the resulting template instantiations polymorphically, e.g. you don't want to store/exchange different foo<string> implementations in the same place. In other words, the only purpose of the pure virtual function seems to make the implementation of computation() by the client mandatory.
You further want the constructor of your template be usable without the client having to reimplement or explicitly import it to his class. That can be achieved only if my_foo is an instance of foo and not a derived class.
In that case, you could use policy based design:
template<typename T, typename ComputationPolicy>
struct foo : ComputationPolicy {
foo(T t) {
//code
}
void bar() {
double d = ComputationPolicy::computation(); //just use it!
}
//...
};
Users of the template now have to define a type that has a function computation(), returning a value convertible to double, otherwise the template can't be instantiated:
struct myComp {
double computation() { return 9.99; }
};
typedef foo<std::string, myComp> my_foo;
my_foo("hello");