Say I have an object of class baseclass:
// baseclass.h
class baseclass
{
baseclass() # default constructor, constructs baseclass object
}
And in the .cpp for baseclass:
// baseclass.cpp
baseclass::baseclass()
{
// member functions and variables
}
Now my goal is to have a derived class, and in the default constructor for the derived class, create an array of static size n baseclass objects. To try and clarify, an alternative way to think about this is to think about baseclass as playing cards, and I want to create an array (a deck) of those cards by calling the default constructor on the derived class. I decided to keep the scope of my question abstract however, so I will continue to use base/derived so others can more easily see how this could apply to them.
I am not sure the best way to set this up in an object oriented manner, so far I have something like this, but I am getting a segmentation fault. Here is how I have it set up:
// derivedclass.h (extending baseclass)
class derivedclass
{
// default constructor for derivedclass object
derivedclass();
// a pointer to an object of type baseclass
baseclass* bar;
// or should it be:
baseclass* bar[n] // where n is an integer
// or is there a better way to do it?
}
Lastly, since I said that a derivedclass object can have an array, I must make that true for the default constructor in the .cpp for derivedclass:
// derivedclass.cpp
derivedclass::derivedclass()
{
// so I need to initialize the member array
baseclass* bar = new baseclass[n] // where n is the size I want to initialize
// the array to
}
So would any of the situations I listed cause segmentation fault? What is the best way to create this array of object? Sorry if this is a nooby question, I am a student still learning a lot about memory allocation and pointers, normally deal with languages where I don't have to worry about this. Also, I tried to keep the question abstract for the benefit of others. Thanks in advance!
I am not sure why you need to use dynamic allocation at all here. I would rather do something like this, which would also save you some work in derivedclass's constructor:
struct baseclass
{
// Stuff...
};
struct derivedclass : baseclass
{
// Stuff...
baseclass objects[N];
};
In C++11 you should use std::array<> instead of a plain C-style array (std::array<> is a safe, zero-overhead wrapper of a C-style array):
// ...
#include <array>
struct derivedclass : baseclass
{
// Stuff...
std::array<baseclass, 10> objects;
};
// so I need to initialize the member array
baseclass *bar = new baseclass[n];
Except that with this, you don't initialize the member array, only a local variable that has the same name as the member variable, thus it shadows it (and for the very same reason, you're also leaking memory by loosing the pointer to the newly allocated array).
Why to use new at all? Why to derive deck from cards? Deck contains cards.
class Card
{
// ... whatever card does
};
class Deck
{
public:
static int const CountOfCards = 36;
typedef std::array<Card,CountOfCards> Cards;
Cards cards;
// etc. ... whatever deck does
};
Related
I have the following problem. I have unique_ptr to an array of a base class A. Which in pure C++ is no problem to initialize with a pointer to an array of a derived type B. Now with the unique_ptr<A[]> I fail to get this working. I don't see the issue and want to avoid going the custom deleter route. I there something other off with my approach?
struct A {
virtual ~A() {};
};
struct B : public A {
int min, max;
};
unique_ptr<A[]> a_arr;
// fails
a_arr.reset(new B[2048]);
a_arr = make_unique<B[]>(2048);
// works
A* a_raw_arr = new B[2048];
You cannot store elements of a derived type in an array of the base tape because they will not fit. What you can do is to have an array of pointers.
#ChristopherYeleighton gave you the reason. The way around is to use an array of unique_ptr as opposed to a unique_pointer to an array.
std::unique_ptr<A> a_arr[2048] = {std::make_unique<B>()};
Alternatively, a std::vector of unique_ptr<A> would also work.
The main thing you gain of this is that you are now allowed to have pointers to different derived classes in your a_arr.
I am currently trying to create a class that has a member object with a non-default constructor for an Arduino project. The object is a pointer so that I can construct when MyClass is constructed (MyObjClass *my_obj;)
// MyObjClass:
class MyObjClass(){
const int param;
public:
MyObjClass(const int param): param(param){ ... }
};
// MyClass:
class MyClass(){
MyObjClass *my_obj;
public:
MyClass::MyClass(const int param): my_obj(param){ ... }
};
It builds fine, but the value param in my_obj is rubbish (random value). Does it already initialize the object before the constructor call? My workaround is to use no const values but there must be a better way (the right way).
You are holding pointer to MyObjClass and try to init him with some int, the
right way will be my_obj(new MyObjClass(param)).
Also I would suggest to use smart pointers to avoid memory leaks.
I got assigned the task to clean up a class hierarchy, but I'm stuck in a bit of a rut. I'm now left with something that roughly looks like this:
class Base
{
Base() = 0;
function1();
...
function5();
protected:
int variable1_;
...
int variable10_;
};
class DerivedOne
: public Base
{
DerivedOne() = 0;
function6();
...
function10();
protected:
int variable11_;
...
int variable20_;
};
class DerivedTwo
: public DerivedOne
{
DerivedTwo()
: DerivedOne()
{
... Fill variable1_ to variable25_ with data read from file ...
variable1_ = ...
}
function11();
...
function15();
private:
int variable21_;
...
int variable25_;
};
So 25 variable are assigned their values in DerivedTwo, making it easy to make a mistake. When another class inherits from DerivedOne, it's almost certain that that person will forget to initialize one of the variables.
I've been playing around with different ways of designing this hierarchy, but nothing really feels right.
I understand it's difficult to say something concrete without knowing what these classes actually do, but I would be interested in knowing if there is something fundamental wrong with this design, or if I have overlooked some elegant way of initializing all the variables.
The principle in derivation is that base object is constructed first, and the derived afterwards. This requires the Base and DerivedOne constructor to produce a valid object on its own.
When constructing DerivedTwo, your code makes this clear:
DerivedTwo()
: DerivedOne() // First the base object constructor is called, before anything else
{
// then remaining initialisation, after DerivedOne() was created
}
So each class should at least initialise its own variables to an initial valid state that its own functions can handle in a consistent manner.
Base() : variable1_(/*default value here*/), variable10_(/*default value here*/) {}
Base(int v1, int v10) : variable1_(v1), variable10_(v10) {} // for convenience
One derived class could overwrite variables of its base class afterwards. It would of course be safer and more elegant to use getters/setters, but its ok.
If you adopt this design, if one subderived class forgets to initialise a variable one of its parents, this should not lead to a catastrophee because at least the base object is initialised in a decent manner.
Now the problem is that you also initiate your DerivedTwo by reading a file. Remember, first Base is created, then DerivedOne, and then only DerivedTwo reads the values. What happen when the file cannot be read or is unconsistent ? You might end up having an inconsistent object, unless your throw an exception. So you have to manage this and make sure that DerivedTwo is in a stable state:
DerivedTwo()
: DerivedOne() // First the base object constructor is called
{
// then initialise all own members to a consitent state
// then try to read the file and manage potential errors
}
Each class should be responsible for initializing its own data members. As you identified, it is dangerous for Base to assume that DerivedX will initialize its data members. So...
Base should initialize variable1_ ... variable10_
DerivedOne should initialize variable11_ ... variable20_
DerivedTwo should initialize variable21_ ... variable25_
...and so on.
Of course, this doesn't address the question of why the classes are laid out in such a fashion...
Lately I have been having difficulties with constructors, and the different attempts from other questions and guides always have some form of segfault waiting for me at runtime (making compiling 80% of my time spent programming).
The following example shows the basic idea on what I am trying to accomplish:
struct Coord3{
float x, y, z;
Coord3() {x=0;y=0;z=0;};///Is this Correct?
};
struct Stat{
int Str,Dex,Int;
Stat(){Str=0;Dex=0;Int=0;};
};
struct Item{
Stat myStats;
Item(){...};
};
class SimpleChar{
public: ///to keep things simple for now
Coord3 pos;
Stat myStats;
int level;
float health;
Item inventory[20];
SimpleChar(){
level=0;
health=100;
}///What happens with 'pos', 'inventory' and 'myStats' in this class's constructor?
};
int main(){
SimpleChar myChar;
if(myChar.inventory[0].get()!=NULL){...}///this caused the most recent SEGFAULT as mentioned below. Why wouldn't this work?
}
With this example I have a bunch of simpler structs (similar to Coord3 and Stat). These structs are at the base level of my "engine", and are used accordingly to make higher level structs, then those are used to make the highest level structs (such as Item being item related information and SimpleChar having generic RPG character statistics, like an inventory and stats). The errors I get are so different according to the situation that it was difficult to keep track them all, but the most interesting one was a SEGFAULT on:
if(itemSet.inventory[a].get()!=NULL); ///Note: this is originally a shared_ptr AND was in a struct known as 'ItemSet', which held all item information
So basically what I ask is:
When are the default constructors invoked?
When the constructors are used, do they also invoke their member's constructors?
What would be the correct way to declare these members both in the classes and main()?
What is the correct way to create the constructor?
EDIT: The code has been spruced up for anyone that is way too obsessed with if the code is "valid by syntax" instead of actually answering the question.
EDIT 2: Since the SEGFAULTs are not created from constructor format then I ask if it is possible to get a SEGFAULT if an instance variable is too large in size? I mainly ask this because recently I have changed a class member to a pointer instead of an object and it worked fine.
when you declear a class like:
class foo{
public:
foo(){} // this is default constructor
};
But if you write:
class foo{};
The compiler will supply a default constructor for you. When you write:
class SimpleChar{
Coord3 pos; // default constructor of Coord3 will be called,
//if you need somrthing else do that in SimpleChar constructor;
Stat myStats; // same
int level;
float health;
Item inventory[20]; // an array will be created that can hold 20 item,
// constructor (default) will be called 20 times
};
Inside main() if you want to initialise an object with default constructor:
className instanceName;
is enough.
When You write:
SimpleChar myChar;
The following constructor is called:
SimpleChar(){
level=0;
health=100;
};
An additional point ; is mandetory after a class or struct definetion, which is absent in struct item{}
And default access specifier of struct is public but in class it is private, Which means you can not create object in main with default constructor.Edit:
"if an instance variable is too large in size" you may get a std::bad_alloc if it is being allocated dynamically in runtime but generally not a segfault. it happens when you access area you do not own.
1: When are the default constructors invoked?
Default constructors are called when:
You create an object without passing parameters
MyClass* myClass = new MyClass(); //<- this is you invoking it.
When you inherit from a class and dont specify a constructor in the initialization list for that base class.
class MyClass: public BaseClass
{
MyClass()
{
}
};
MyClass* myClass = new MyClass(); // <-- this will invoke the default constructor for "MyClass" and "BaseClass".
When you put an object in any stack and dont specify a constructor.
void methodA()
{
MyClass myClass; // <-- this will invoke the default constructor for "MyClass"
}
Same happens if you declare an object as a member of a class in its stack.
class MyClass
{
MyClass()
{
}
DifferentClass m_member;
};
If you dont specify a different constructor for m_member in the initialization list of MyClass, its default constructor will be used.
2: When the constructors are used, do they also invoke their member's
constructors?
As long as they are in the stack and not in the heap, and you dont specify otherwise in the initialization list of the class. Yes.
3: What would be the correct way to declare these members both in the
classes and main()?
It will depend on what you want, if you want to initialize them with its default constructor, you can just declare them as follow:
MyClass myClass; //<- this is fine.
4: What is the correct way to create the constructor?
A good practice is to ALWAYS initialize your members in the initialization list, for example:
struct Stat
{
int Str,Dex,Int;
Stat(): Str(0), Dex(0), Int(0)
{};
};
A simple example of how the default constructor works:
class base
{
int i;
public:
base()
{
i = 10;
cout << "in the constructor" << endl;
}
};
int main()
{
base a;// here is the point of doubt
getch();
}
I works on embedded software. Previously we don't use too many C++ features so we use memset(this,0,sizeof(child)) to initialize(zero out) a object. However it doesn't work now since we are using virtual functions. Apparently it would destroy the vtable/virtual pointer.
So my question is:
How can I initialize an object quickly and conveniently?
The class child inherits from class parent, which defines a lot virtual functions, and got many data member. If I need only to zero out all data member, any way to avoid member-by-memeber assignment in child's constructor without using memset()? or any trick to use memset without destroying vtable? (compiler-independent way)
Thank you very much.
You're asking to utilize the facilities of C++ but don't want the performance-hit of per-member initialization. Firstly, I'd ask myself if this is really the hit you're talking about. There are plenty of more bottlenecks you can be looking for than setting a member to 0.
But, if you want the features of C++ and still want the speed of memset() then I suggest you put the data for this class in a different class and initialize that to 0 and pass it to the class that is going to use it by reference.
Using placement new is definitely an option to avoid member wise zeroing out memory. Use delete[] to delete memory.
struct base{virtual ~base(){}};
struct derived : base{};
int main()
{
char *p = new char[sizeof(derived)];
memset(p, 0, sizeof(derived));
derived *pd = new (p) derived;
}
DISCLAIMER: This is a cheap and dirty hack, not very C++ish, and haters will hate it. But hey. If you gotta do what you gotta do, and what you gotta do it to is a POD, then this will work.
If you can take the data members that you want to memset and put them in their own POD, you can memset that POD. To wit (the POD in question here is the BucketOBits struct):
NOTE: It is important that the datatype you use here is a POD (Plain Old Data). For more about what this means, see this FAQ entry.
#include <cstdlib>
#include <cstring>
class Interface
{
public:
virtual void do_it() const = 0;
virtual ~Interface() {};
};
class Object : public Interface
{
public:
Object();
void do_it() const {};
private:
struct BucketOBits
{
int int_a_;
int int_b_;
int int_c_;
} bucket_;
};
Object::Object()
{
memset(&bucket_, 0, sizeof(bucket_));
};
int main()
{
Interface* ifc = new Object;
}
Even better, you can use the fact that value initialization for integral types means zero-initialization, and get rid of the memset entirely, while at the same time maybe even making your code a little faster than if you had used memset. Use default construction for BucketOBits in the constructor's initialization:
Object::Object() : bucket_()
{
};
EDIT2:
If both base & derived classes have data members that need this zero-init, then you can still use this method by giving each class it's own BucketOBits. Case in point:
#include <cstdlib>
#include <cstring>
class Interface
{
public:
virtual void do_it() const = 0;
Interface();
virtual ~Interface() {};
private:
struct BucketOBits
{
unsigned base_int_a_;
unsigned base_int_b_;
long base_int_c_;
} bucket_
};
class Object : public Interface
{
public:
Object();
void do_it() const {};
private:
struct BucketOBits
{
int int_a_;
int int_b_;
int int_c_;
} bucket_;
};
Interface::Interface() : bucket_()
{
}
Object::Object() : bucket_()
{
}
int main()
{
Interface* ifc = new Object;
}
First, you cannot avoid using the constructor, because it will be called automatically when you create the object. If you do not define a constructor yourself, the compiler will define one for you. By the time you call memset(this), which BTW you should never ever do, the constructor has already been called.
Second, in C++ initialization and assignment is not quite the same thing. Initialization is actually faster, which is why you should initialize the data members in the constructor's initialization list, rather then assign values to them in the body of the constructor.
In short, I would advise you not to fight the language.
any trick to use memset without
destroying vtable?
(compiler-independent way)
There is no way to work-around this platform independent.
The reason is that vtable not placed in a specific address, but could be in the begining of the object, or right after the last data member. So it is not portable to start calculating addresses and jump over it. Also there is the size of pointer depending on architecture etc.
For multiple inheritance it gets worse.
You should use either an initialization list (not assignment in constructor) or placement new
as Chubsdad's answer.
If I need only to zero out all data
member, any way to avoid
member-by-memeber assignment in
child's constructor without using
memset()?
You can not (and must not) avoid calling the constructor in this context, since it is the constructor that initializes the vtable pointer