container of shared_ptr to base class and protected pure virtual method

closed account (iA7Ly60M)
I have been working on a little project for a while now and it was going pretty good until I ran into a little bit of a problem. Consider this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <memory>
#include <vector>

class Base
{
protected:
	virtual void print(int x, int y) const = 0;
};

class DerivedAbstract : public Base
{
protected:
	virtual void dummy() = 0;
	void addChild(std::shared_ptr<Base> ptr) { children.push_back(ptr); }
	std::vector<std::shared_ptr<DerivedAbstract>> children;
};

class Derived2 : public DerivedAbstract
{
protected:
	void dummy() override {}

	void print(int x, int y) const override	{
		for(auto it = children.begin(); it != children.end(); ++it)
			it->get()->print(503, 747);
	}
};


This is of course not the code I'm working with but this is to show you the problem.
I have a base class that contains a pure virtual method that has to be implemented in every class that derives from it (to be able to print it). I have the first derived class that implements even more pure virtual methods (dummy()) and a vector of pointers to itself, which is kind of like a "children" vector.
The most important thing about these is the vector. I want to be able to call the overriden method "print()" on every element in the vector. Sadly though, it is not possible as the function is not accessible. How to explain to the compiler that I want to call the overriden print() method, not the base one like it is assuming.
There will also be more classes that derive from "DerivedAbstract", like "Derived3", "Derived4"... that will be put into the vector.

The print method has to stay protected (I don't want to be able to call it from anywhere in the code, plus I can't change it since it belongs to some external library class).
Last edited on
How to explain to the compiler that I want to call the overriden print() method, not the base one like it is assuming.

This should be done automatically at runtime

do you want the elements in your vector to be of type DerivedAbstract or Base?
If you make it a vector of pointers to Base Objects you can do what you want, if you have one of DerivedAbstract pointers then you'll have to change the declearation of your addChild...

1.) hold DerivedAbstract
1
2
void addChild(std::shared_ptr<DerivedAbstract>ptr) { children.push_back(ptr); }
std::vector<std::shared_ptr<DerivedAbstract>> children;

2.) hold Base and insert Base pointers
1
2
void addChild(std::shared_ptr<Base>ptr) { children.push_back(ptr); }
std::vector<std::shared_ptr<Base>> children;

3.) hold Base and insert DerivedAbstract pointers
1
2
void addChild(std::shared_ptr<DerivedAbstract>ptr) { children.push_back(ptr); }
std::vector<std::shared_ptr<Base>> children;
Last edited on
Just make Derived2::print() public. Why do you want it to have less visibility than the function the base class?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <memory>
#include <vector>

struct base
{
    protected: virtual void print( int x, int y ) const = 0;
};

struct derived_one : base
{
    void add_child( std::shared_ptr<derived_one> ptr ) { children.push_back(ptr); }

    protected:
        virtual void dummy() = 0 ;
        std::vector< std::shared_ptr<derived_one> > children ;

        ////////////////////////////////////////////////////////////////////////////////////////////
        // > I don't want to be able to call it from anywhere in the code

        // protected static helper function:
        // can be called by members and friends of derived classes
        // but can't be called from anywhere else in code
        static void do_print( std::shared_ptr<derived_one> ptr, int x, int y  ) { ptr->print(x,y) ; }
        ////////////////////////////////////////////////////////////////////////////////////////////
};

struct derived_two : derived_one
{
    protected:
        virtual void dummy() override {}

        virtual void print( int x, int y ) const override
        { for( const auto& ptr : children ) do_print( ptr, x, y ) ; }
};
closed account (iA7Ly60M)
1.) hold DerivedAbstract
1
2
void addChild(std::shared_ptr<DerivedAbstract>ptr) { children.push_back(ptr); }
std::vector<std::shared_ptr<DerivedAbstract>> children;

I am very sorry for the confusion, but I was meant to edit my post to make two changes but I ended up making just one, which was changing the vector type (I forgot about the method parameter). But it doesn't matter since it doesn't fix it.

1
2
3
4
static void do_print( std::shared_ptr<derived_one> ptr, int x, int y  ) { ptr->print(x,y) ; }
...
virtual void print( int x, int y ) const override
        { for( const auto& ptr : children ) do_print( ptr, x, y ) ; }

I think I'm going to have to go with this one. Thanks for your help.
I want to be able to call the overriden method "print()" on every element in the vector. Sadly though, it is not possible as the function is not accessible.

I still don't understand the problem here.

From where do you want to call the print() method on each elements on the vector?
From outside the class or from a derived one or maybe from itself?

How to explain to the compiler that I want to call the overriden print() method, not the base one like it is assuming.

Calling the base-print method would result in a crash because it's a pure virtual function call. I never encountered that problem, I wouldn't even know how you'd get this problem.
Topic archived. No new replies allowed.