vector< unique_ptr<T> > as base class member - c++

I have three classes:
Class Something
{...}
Class A
{
public:
A();
virtual ~A() = 0; //have also tried this as non-abstract
std::vector< unique_ptr<Something> > somethings; //have tried this just as std::vector<Something*> as well
};
class B : public A
{
B();
...
}
if I leave out the declaration of std::vector< Something* > somethings, from class B... then my compiler tells me that class class ‘B’ does not have any field named ‘somethings’.
So if I add it back in, and I try to reference it like so
A *a = new B();
for(auto it = a->somethings.begin(); it != a->somethings.end(); it++)
{
Draw((*it)->image,(*it)->x, (*it)->y, NULL, (*it)->angle);
}
It says that a->somethings is empty... even though if I print from B itself to tell me how many 'somethings' there are, it is accurately reporting the count. This is what led me to remove std::vector< unique_ptr > somethings; from class B to begin with, as I suspected it was somehow getting A's vector instead, even though it's abstract.
Bonus: This all works if I go B *b = new B(); just broke when I added the parent class A and made B inherit from it.

From the linked code in your comment, the problem is that you're trying to initialize the base class field directly in the derived class. You can't do that (and it makes no sense to try) as the base class fields are initialized by the base class constructor. If you want to initialize the field (rather than assigning to it), you need to do it in the base class constructor:
class Base {
public:
std::vector<float> fVec;
Base(std::vector<float> v) : fVec(v) { }
};
class Derived : public Base {
public:
Derived(std::vector<float> v) : Base(v) {
:
Note that the code you show above is completely different from and unrelated to what you linked to -- you should post the code that pertains to your question, and not unrelated irrelevant code.

I'm not sure if this will help you, but I made a small change to your coliru.stacked-crooked example as follows:
#include <vector>
class Base
{
public:
std::vector<float> fVec;
};
class Derived : public Base
{
public:
Derived(std::vector<float> v) // : fVec(v)
{
fVec = v;
}
};
int main() {}
Notice I commented out the fVec from the constructor initialisation list and assigned it in the body of the constructor. The problem here is that your Base object hasn't been created fully until you enter the opening brace of the body of your Derived constructor.
To work around this issue, you could add a constructor to your Base object that takes a vector and then assign that to your object, more or less what Chris said.
Both examples above work for me, but I don't have your full code so can't be sure they'll fix all your problems. I thought I'd take a punt anyway.
You probably know all about the copies of vectors being made and should be passing them as const refs, but that's another issue.

Related

Cannot return vector containing derived pointers

Okay, so to illustrate the issue I am having I will show some (pseudo) code.
Lets say I have the following models:
class Animal : public GameObject;
class Player : public GameObject;
class GameObject : public ObjectInterface;
class ObjectInterface
{
public:
virtual ~ObjectInterface() = default;
virtual vec3 GetPosition() = 0;
}
Now I also hold some "object context", which holds collections of certain game objects.
class ContextObject
{
// they implement ObjectInterface
vector<shared_ptr<Animal>> animals;
vector<shared_ptr<Player>> players;
}
Now I have a TargetSelector class, which works directly with the ObjectInterface only.
class TargetSelector
{
// this is somehow not possible, although `animals` are a subclass of `ObjectInterface`
vector<shared_ptr<Model::ObjectInterface>>& GetAvailableTargets()
{
return context->animals; // context is some `ObjectContext`
}
}
I would expect the above code to work, since an Animal is of the type ObjectInterface. But instead I get an error saying it cannot convert from an vector<shared_ptr<Animal>> to an vector<shared_ptr<ObjectInterface>>. Is this even suppose to work?
Could someone explain me why I cannot do this kind of polymorphism and if possible a nice solution so I can make this work.
Thanks, any help is appreciated!
I would expect the above code to work, since an Animal is of the type ObjectInterface.
Unfortunately, class templates don't work that way.
Given
struct Base {};
struct Derived : Base {};
Derived d;
Base& bref = d; // OK.
Base b = d; // OK.
However, given
template <tpename T> Foo {};
Foo<Derived> d;
Foo<Base>& bref = d; // Not OK
Foo<Base> b = d; // Not OK.
Derived is a sub-type of Base does not imply Foo<Derived> is a sub-type of Foo<Base>.
That analogy applies to shared_ptr too. Your problem is compounded by use of another layer of class template. shared_ptr<Derived> is not a sub-type of shared_ptr<Base>. Never mind being able to use vector<shared_ptr<Derived>> when a vector<shared_ptr<Base>> is exepcted.
You can use vector<shared_ptr<ObjectInterface>> in all the places and make sure to cast to the appropriate shared_ptr type before using it.
Check out the various pointer_cast functions at http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast.

Can't access protected member variables of the most base class through std::unique_ptr in diamond

I am not an advanced programmer. Suppose there is a classic diamond inheritance:
class Base
class A: virtual public Base
class B: virtual public Base
class Last: public A, public B
Suppose Base has a variable, m_x, that is common to both A and B, such that only one of A, or B, can be called at a time, not both (which is what is needed). To get around this, this is used:
class Last: public A, public B
{
private:
std::unique_ptr<Base> m_p;
public:
Last(int i)
{
if (i)
m_p = std::unique_ptr<Base>(new A());
else
m_p = std::unique_ptr<Base>(new B());
}
};
This is fine, but now m_p->m_x cannot be accessed anymore because it says it's protected, but both A and B call m_x in their constructors directly, with no problems.
Is this a known limitation or is this the wrong way to do it? If it's wrong, what solutions are there?
Here is some code based on the diagram found here (a bit lower on the page):
#include <iostream>
#include <memory>
class Power
{
protected:
double m_x;
public:
Power() {}
Power(double x): m_x {x} {}
virtual ~Power() = default;
};
class Scanner: virtual public Power
{
public:
Scanner() {}
Scanner(double x): Power(x) {} // scan document
};
class Printer: virtual public Power
{
public:
Printer() {}
Printer(double x): Power(x) {} // print document
};
class Copier: public Scanner, public Printer
{
private:
std::unique_ptr<Power> m_p;
public:
Copier() {}
Copier(double x, int i)
{
if (i)
m_p = std::unique_ptr<Power>(new Scanner(x));
else
m_p = std::unique_ptr<Power>(new Printer(x));
}
void print() { std::cout << this->Power::m_x << '\n'; }
};
int main(int argc, char *argv[])
{
Copier *copier {new Copier(1.618, 0)};
copier->print();
copier = new Copier(3.14, 1);
copier->print();
return 0;
}
Using both this->m_p and this->Power::m_x (according to answers and comments) compiles, but the output is 0.
To be sure I spell it out all: not only I am quite a beginner, but, given the example above, it oesn't really have to stay that way if there is another alternative to call Scanner or Printer only one at a time from inside Copier. I am not asking for opinions, I understand it's forbidden, but I won't reject them coming from more experienced users. After all, I am learning.
Both virtual inheritance and std::unique_ptr are red herrings. The problem comes down to this:
class Base
{
protected:
int m_x;
};
class Last : public Base
{
public:
Last()
{
Base base;
base.m_x = 0; // error
m_x = 1; // no error
}
};
The error is something like error C2248: 'Base::m_x': cannot access protected member declared in class 'Base' or error: 'int Base::m_x' is protected within this context.
The explanation is that protected is a somewhat special case. It does not only work on class level but also on the object level. And you have two relevant objects here:
The Last object which is being created by the constructor, i.e. the one pointed to by this. It's also a Base object because of the is-a inheritance relationship.
The local object named base within the constructor.
Now, the problem is that in the line base.m_x = 0;, you are in the context of the first object and not the second one. In other words, you are trying to access the m_x of base from outside base. C++ simply does not allow this.
A very technical explanation can be found in the C++ standard at §11.4 [class.protected], a more easily understandable one in an excellent answer here on Stack Overflow.
protected doesn't mean quite what you think it does.
Although Last is derived from Base, member functions of Last don't have access to the protected members of any Base object - just those Base objects that are sub-objects of some Last object.
So you can write: this->Base::x because *this is a Last object, but not m_p->x, because *m_p is of static type Base.
As others have noted, I think this is actually an XY problem. Having an object which derives from two classes, and then also has a pointer to another object of one of those classes is very strange indeed. I think you need to clarify what you are trying to do.

Initialize Inner Class with outer class this possible?

Today i tried to instanciate an inner class while passing my outer class to it and while i am in the namespace of the outer class:
I'm using Visual Studo 2013.
Code looks like this : (watch the ^^)
class Base
{
public:
virtual void foo(){ cout << "foo" };
};
class object
{
class Derived : public Base
{
object& o;
public:
Derived(object& o) : o(o){}
virtual void foo(){ cout << "bar" };
}derived(*this);
// ^^^^^^
};
The derived class inheriting something does not affect anything for this example here as far as i tested. (only in here for context reasons , see below)
On this ^^ point i recieve error:
no appropriate default constructor available
Intellisense warns me, that it expects type specification.
I also tried passing a pointer (of course i changed construktors then, too)but same reaction.
For protokoll i tried quite a lot of variations and research by now, but i cannot isolate a clear answer to my problem.
Is the "this" pointer not usable here ? How can i pass myself then at this point ?
For Background (only if you're interested):
I tried to write Code for Keybinding in an Application. To pass
functions to the Keys i use an "Interface" of class KeyFunction (Base
class resembles it).
I now want to give classes (object) the possibility to declare it's
own KeyFunction(Derived) and , more important, pass ressources(object)
with it, in a way that functions can work on them (since i can only
use void pointers, because they are later stored in an array for the
bindings) I already achieved this task with other code which i think
is to long to post here, though. By experimenting i stumbled across
this problem.
Your compilation error has nothing to do with your class hierarchy, but with the simple fact that this is not how you go about constructing a class instance.
Try actually declaring a class member, and a class constructor:
class Base
{
public:
virtual void foo(){ }
};
class object
{
class Derived : public Base
{
object& o;
public:
Derived(object& o) : o(o){}
virtual void foo(){ }
};
Derived derived;
object() : derived(*this)
{
}
};

C++ polymophism issue, Instantiating from child class; NOT to declare abstract class as pointer

Suppose we have an Abstract class and child (derived from abstract) classes. I know we can instantiate from derivedClass like this:
AbstractBase *foo = new DerivedClass1();
But, is this the right way to define the top line code:
AbstractBase foo = *(new DerivedClass1());
I don't want to declare the Abstract class via pointer. But, What is the best way to do this and manage the memeory leak?
Thanks a lot
AbstractBase foo = *(new DerivedClass1()); will try to construct an instance of AbstractBase (which you can't do, it's abstract) using a constructor which takes an object of type DerivedClass1 (or something it's convertible to.
If you don't want to end up with a pointer to AbstractBase, but you do want to use new to allocate the object dynamically, then you probably want:
AbstractBase& foo = *(new DerivedClass1());
to define a reference to AbstractBase from your new DerivedClass1
Here is a very simple example of how to "chain" copy constructors. Note that the syntax may be a bit off, but this is the general idea:
class ABase {
public:
ABase(const ABase& ab) {
basevar = ab.getBasevar();
}
int getBasevar() { return basevar; }
private:
int basevar;
};
class c1 : public ABase {
public:
c1(const c1& c) : ABase(c) {
cvar = c.getCvar();
}
private:
int cvar;
};
In particular, note the use of the : operator between the function declaration and definition; this space allows for multiple direct assignments in a constructor function (possibly in other functions as well) and its content is called an "initialization list". Note also this answer which details some more examples.

Call a base class constructor later (not in the initializer list) in C++

I'm inheriting a class and I would like to call one of its constructors. However, I have to process some stuff (that doesn't require anything of the base class) before calling it. Is there any way I can just call it later instead of calling it on the initializer list? I believe this can be done in Java and C# but I'm not sure about C++.
The data that I need to pass on the constructor can't be reassigned later, so I can't just call a default constructor and initialize it later.
Is there any way I can just call it later instead of calling it on the initializer list?
No, you cannot. The base class constructor must be called in the initializer list, and it must be called first.
In fact, if you omit it there, the compiler will just add the call implicitly.
I believe this can be done in Java and C# but I'm not sure about C++.
Neither C# nor Java allow this either.
What you can do, however, is call a method as an argument of the base class constructor call. This is then processed before the constructor:
class Derived {
public:
Derived() : Base(some_function()) { }
private:
static int some_function() { return 42; }
};
As was said by several people answering, you cannot delay the invocation of a base class constructor, but Konrad has given a good answer that might well solve your problem. However, this does have its drawbacks (for example, when you need to initialize several functions with values whose calculations share intermediate results), so just to be complete, here's another way of solving the problem of fixed initialization order, by using it.
Given the fixed order of initialization, if you have control over the derived class (and how else would you come to fiddle with one of its ctors?), you can sneak in a private base so that it is going to be initialized before the other base, which can then be initialized with the private base's already calculated values:
class my_dirty_little_secret {
// friend class the_class;
public:
my_dirty_little_secret(const std::string& str)
{
// however that calculates x, y, and z from str I wouldn't know
}
int x;
std::string y;
float z;
};
class the_class : private my_dirty_little_secret // must be first, see ctor
, public the_other_base_class {
public:
the_class(const std::string str)
: my_dirty_little_secret(str)
, the_other_base_class(x, y, z)
{
}
// ...
};
The my_dirty_little_secret class is a private base so that users of the_class cannot use it, all of its stuff is private, too, with explicit friendship granting only the_class access to it. However, since it's listed first in the base class list, it will reliably be constructed before the_other_base_class, so whatever it calculates can be used to initialize that.
A nice comment at the base class list hopefully prevents from others breaking things by refactoring.
IMHO I dont think it is possible to defer calling the base class constructor in the way that you mentioned.
Wow, we were all young once. This answer won't work, so don't use it. Content left for historical purposes.
If you have full control over the base class, I'd recommend adding a protected method to do the class initialization, make it virtual, and put the your derived class implementation details in it before it calls its base:
class Base
{
public:
Base()
{
Initialize();
}
protected:
virtual void Initialize()
{
//do initialization;
}
};
class Derived : Base
{
public:
Derived() : Base()
{
}
protected:
virtual void Initialize()
{
//Do my initialization
//call base
Base::Initialize();
}
};
Another option, based on the suggestion from #Konrad is to have a static method to construct the object, e.g.:
class Derived {
public:
Derived(int p1, int p2, int p3) : Base(p1, p2) { }
static Derived* CreateDerived(int p3) { return new Derived(42, 314, p3); }
};
Ive found this useful when extending a class from a library and having multiple parameters to override.
You can even make the constructor private
struct base{
base(int x){}
};
struct derived : base{
derived(int x) : base(x){}
};
This is how base class constructors are invoked in C++ from the initialization list of derived class.