Instantiating an object as class member without default constructor - c++

I am a newbie to C++. I want to declare an object as a private member of another class. Is the instantiation of this object can be done with out the default constructor? A sample code is listed here:
class Vertex{
int i;
public:
Vertex(int j):i(j){};
Vertex(const Vertex & v){i=v.i;};
}
class Test{
Vertex v;
public:
Test(const Vertex & v1){v(v1);}
}
int main()
{//some code here;
Vertex v1(int j=1);
Test(v1); // *error: no matching function for call to 'Vertex::Vertex()'*
return 0;
}
It appears to me once declared an object as a private class member (e.g. Vertex v), the default constructor is immediately sought after. Anyway to avoid this? Thanks a lot.

Vertex v1(int j=1);
This declares a function, v1, which returns a Vertex and takes an int argument. What you want is
Vertex v1(1);
in addition, you need to use initialiser lists as the other answers have shown:
Test(const Vertex & v1) : v(v1) {}

Initialise Test::v just as you initialised Vertex::i. (It being private is entirely irrelevant!)
So, using Test::Test's member initialisation list:
Test(const Vertex & v1) : v(v1) {};
For consistency, then, I would also suggest:
Vertex(const Vertex & v) : i(v.i) {};
Initialise members wherever you can.

Use the constructor initialization list:
Test(const Vertex & v1) : v(v1) {}
Once you're in the constructor's body (between the { and }), all data members have been initialized. If you don't do it explicitly, they get default initialized, which requires an available default constructor for user defined types.
Next, you are declaring a function here:
Vertex v1(int j=1);
What you probably meant is
Vertex v1(1);

Related

Constructor invocation order for member objects

I have the following class called Tree, which has a member object of class Leaf. Leaf requires a parameter from Tree (height_) for its construction. I can write an intialize method for this. But do we know the order in which constructors are called, so that dependencies in the construction of member objects are met when the Tree class is constructed?
In other words, when there is dependency in the instantiation of a member object, is an separate initialization method (for the member object) the only way to go?
A minimal code below, I have put a question mark in the argument to the constructor of Leaf to indicate my question:
class Tree {
private:
float height_;
Leaf leaf_(?);
public:
explicit Leaf(const std::istream& input);
};
void Tree::Tree(const std::istream& input){
// read height_ from input
...
}
class Leaf {
private:
float height_fraction_;
public:
// height is required for construction of Leaf class
Leaf(const float& height);
};
void Leaf::Leaf(const float& height)
{
height_fraction_ = 0.5*height;
}
Construction of the members happens in the order in which they are declared. This is very important for the following. If the order of declaration does not match the order in which the dependencies are used, then the program will have undefined behavior.
The initializers with which they are constructed can be specified in the member initializer list of the constructor after after a colon before the function body:
void Tree::Tree(const std::istream& input)
: height_(/* initializer for height_ */),
leaf_(/* initializer for leaf_ */)
{
//...
}
(Instead of parentheses, braces for list-initialization may also be used.)
In the initializer for leaf_, the value of height_ can be used.
Since you probably need to do some work to get height_ from the inputs, you probably want to write an extra function for that and call it for /* initializer for height_ */.

Do we need to clear a class member of type vector in beginning of the constructor function of the class?

I am trying to understand the class definition of a class in this pdf: http://finance.bi.no/~bernt/gcc_prog/recipes/recipes.pdf (Page 61-62). The part of the code where I have the question is below. The following is the header file:
#ifndef _TERM_STRUCTURE_CLASS_INTERPOLATED_
#define _TERM_STRUCTURE_CLASS_INTERPOLATED_
#include "term_structure_class.h"
#include <vector>
using namespace std;
class term_structure_class_interpolated : public term_structure_class {
private:
vector<double> times_; // use to keep a list of yields
vector<double> yields_;
void clear();
public:
term_structure_class_interpolated();
term_structure_class_interpolated(const vector<double>& times, const vector<double>& yields);
virtual ˜term_structure_class_interpolated();
term_structure_class_interpolated(const term_structure_class_interpolated&);
term_structure_class_interpolated operator= (const term_structure_class_interpolated&);
int no_observations() const { return times_.size(); };
virtual double r(const double& T) const;
void set_interpolated_observations(vector<double>& times, vector<double>& yields);
};
#endif
Below is the code file defining the class methods:
#include "fin_recipes.h"
void term_structure_class_interpolated::clear(){
times_.erase(times_.begin(), times_.end());
yields_.erase(yields_.begin(), yields_.end());
};
term_structure_class_interpolated::term_structure_class_interpolated():term_structure_class(){clear();};
term_structure_class_interpolated::term_structure_class_interpolated(const vector<double>& in_times,
const vector<double>& in_yields) {
clear();
if (in_times.size()!=in_yields.size()) return;
times_ = vector<double>(in_times.size());
yields_ = vector<double>(in_yields.size());
for (int i=0;i<in_times.size();i++) {
times_[i]=in_times[i];
yields_[i]=in_yields[i];
};
};
term_structure_class_interpolated::˜term_structure_class_interpolated(){ clear();};
\\ rest of the code not included here
If you look at the two definitions for the constructor function and the definition of the destructor function, the method clear() is called at the beginning, which as I understand makes the size of the class member vectors zero. I don't understand why is that done? Isn't their size already zero?
My second question is why the parent class (term structure class) is being referenced in the below line:
term_structure_class_interpolated::term_structure_class_interpolated():term_structure_class(){clear();};
The thrid question is: Can't we simply use assignment operator in the other constructor definition to initilise times and yields, instead of copying element by element using for loop, like this?
term_structure_class_interpolated::term_structure_class_interpolated(const vector<double>& in_times,
const vector<double>& in_yields) {
times_ = in_times;
yields_ = in_yields;
};
The clear operation is not necessary. By the time you reach the body of the constructor, the vector objects have been default constructed. A default constructed vector is empty.
That is calling the default base class constructor. If no base class constructor call is present, the default is invoked automatically. An explicit base class constructor call is only required if you wish to call a non-default constructor of the base class. Because the code you posted is invoking the default constructor, it is not technically needed. The compiler will do that automatically.
Yes, and that initialization is usually not done in the constructor body:
term_structure_class_interpolated::term_structure_class_interpolated(const vector<double>& in_times,
const vector<double>& in_yields)
: times_(in_times),
yields_(in_yields)
{
};
This calls the copy constructor of the vector rather than the copy assignment operator. This avoids the auto generated call to the vector default constructor that would be inserted by the compiler if you performed the assignment in the constructor body.
Note that doing it this way means you can't simply return when the size of the vectors are unequal like the posted code is doing. If that is required, you need to assign the vectors within the constructor body using the copy assignment operator.

C++: Implicit assignment for Objects

I have been looking for quite some time for my question, but I haven't found any satisfying answer yet.
The question is fairly easy: What should I put between the brackets when I use Implicit Assignment for an Object.
I was always used to seeing something like this: The assign an int, you give it an int-value
class Point2D
{
private:
int m_nX;
int m_nY;
public:
// A specific constructor
Point2D(int nX, int nY)
: m_nX(nX), m_nY(nY) // So the int m_nX gets the int-value nX
{
}
}
But recently I found a tutorial where PARAMETERS were given to an object. (http://www.learncpp.com/cpp-tutorial/102-composition/)
class PersonalComputer
{
private:
CPU m_cCPU;
Motherboard m_cMotherboard;
RAM m_cRAM;
public:
PersonalComputer::PersonalComputer(int nCPUSpeed, char *strMotherboardModel, int nRAMSize)
: m_cCPU(nCPUSpeed), m_cMotherboard(strMotherboardModel), m_cRAM(nRAMSize)
// So the m_cCPU-object is given a parameter nCPUSpeed, and not another m_cCPU-object
{
}
};
So my question is: How does Implicit Assignment work for objects? And how can I assign an Object with an Object itself (e.g. give an m_cCPU2-object to the m_cCPU-object).
Thanks
This is called initialization (not "implicit assignment").
For a primitive type it means that object is given that initial value
int nX(5);
For a class type it means to call the class's constructor with those arguments:
Motherboard m("ABCDE");
To assign an initialize an object with another object in the initializer list you want to define a copy constructor
class CPU
{
CPU(const CPU& other)
: someSpeedVariable(other.someSpeedVariable) // Eg.
{}
}
Then you can do this in other classes.
class PC
{
PC(const CPU& cpu)
:m_cpu(cpu)
{}
CPU m_cpu;
}
I think this is what you're asking?

Is there a way to late-initialize a member variable (a class) in C++?

I am coming from the Java background. I have the following program.
#include <string>
#include <iostream>
class First {
public:
First(int someVal): a(someVal) {
}
int a;
};
class Second {
public:
First first;
Second() { // The other option would be to add default value as ": first(0)"
first = First(123);
}
};
int main()
{
Second second;
std::cout << "hello" << second.first.a << std::endl;
}
In class Second, I wanted to variable first to remain uninitialized until I specifically initialize it in Second()'s constructor. Is there a way to do it? Or am I just left with 2 options?:
Provide a parameter-less constructor.
Initialize it with some default value and later re-assign the required value.
I can't initialize first in the initializer-list with the right value, since the value is obtained after some operation. So, the actual required value for first is available in Second() constructor only.
MY suggestion: Use a function:
private: static int calculate_first(int input) {return input*5;}
explicit Second(int input) : first(calculate_first(input)) {}
Base classes will be initialized in the order they're declared in the class inheritance list, and then members will be initialized in the order that they're listed in the class, so the calculation can depend on non-static member-variables and base classes if they have already been initialized.
Alternatively:
Default constructor, then reassign:
explicit Second(int input) { first = input*5; }
Dummy value, then reassign:
explicit Second(int input) : first(0) { first = input*5; }
Use boost::optional (or std::optional as of C++17):
boost::optional<First> first;
explicit Second(int input) { first = input*5; }
Use the heap:
std::unique_ptr<First> first;
explicit Second(int input) { first.reset(new First(input*5));}
Second(const Second& r) first(new First(*(r->first))) {}
Second& operator=(const Second& r) {first.reset(new First(*(r->first)));}
Placement new:
This is tricky and not suggested
and worse in every way than boost::optional
So sample deliberately missing.
But it is an option.
Initialize first in the member initializer list.
It may help to perform your calculations in a helper function and use a forwarding constructor:
class Second {
public:
Second() : Second(helper_function()) {}
private:
Second(int calc): first(calc) {}
static int helper_function() { return ...; }
First first;
};
This sentence is the core of the problem:
I can't initialize first in the initializer-list with the right value,
since the value is obtained after some operation.
You should know that what you want to do here is not perfect programming style in Java, either. Leaving the field with some default value and then assigning it a bit later after some calculations have been done effectively prevents it from being final, and consequently the class from being immutable.
In any case, your goal must be to push those calculations directly into the initialization of the member, using private helper functions (which may be static):
class Second {
private:
First first;
static int getInitializationData()
{
// complicated calculations go here...
return result_of_calculations;
}
public:
Second() : first(getInitializationData()) {}
};
In my opinion, everything else is just a workaround and will complicate your life in the long run.
You can just do what you said in the comments, or, you can make first a pointer to First and give it memory whenever you like, although i don't recommend this way
One way to separate object lifetimes is to use the heap, make first a pointer and initialize it anytime you like:
class Second {
public:
First* first;
Second() {
first = new First(123);
}
};
of course, you'll probably want to use a smart pointer of some sort rather than a raw pointer.
If you don't code to explicitly initialize a member variable, the default initializer is used to initialize it.
The draft C++ standard has the following about initialization of base classes and member variables:
12.6 Initialization [class.init]
1 When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or the initializer has the form (), the object is initialized as specified in 8.5.
And
12.6.1 Explicit initialization [class.expl.init]
1 An object of class type can be initialized with a parenthesized expression-list, where the expression-list is construed as an argument list for a constructor that is called to initialize the object. Alternatively, a single assignment-expression can be specified as an initializer using the = form of initialization. Either direct-initialization semantics or copy-initialization semantics apply; see 8.5.

Construct object in another class after initializing variables

I have something like the following:
QuadMesh.h:
#include "StructureIpsim.h" // this is a struct
class QuadMesh {
public:
QuadMesh(StructureIpsim s) {//do stuff}
};
SEMPotential.h:
#include "QuadMesh.h"
#include "SpecialFuncs.h"
class SEMPotential {
public:
StructureIpsim SI;
QuadMesh mesh;
SEMPotential( //args);
};
SEMPotential::SEMPotential( //args) {
// init structure in here, need to call functions from SpecialFuncs.h to do so
// How to construct the QuadMesh object mesh? Can't put in initialization list.
}
As you can see, the QuadMesh object takes in a StructureIpsim sruct, but this struct must be initialized using several functions in the constructor of SEMPotential before being passed to the QuadMesh constructor. What's the standard way around this?
You CAN use the initializer-list. Use a helper function, which should probably be a private static member function, that accepts the relevant arguments, does the calculations, and returns a QuadMesh object. Use the initialization list to initialize the member from the return value of that helper.
class SEMPotential
{
static QuadMesh mesh_creator( /* args */ );
public:
QuadMesh mesh;
SEMPotential(/* args */) : mesh(mesh_creator(args)) {}
};
QuadMesh SEMPotential::mesh_creator( /*args*/ )
{
StructureIpsum s;
// init structure in here, calling functions from SpecialFuncs.h to do so
return QuadMesh(s);
}
As Matt McNabb points out in his comment, that helper function could be a constructor of StructureIpsum. But I present a solution that doesn't require modifying StructureIpsum or QuadMesh class definitions.
If you want to preserve the StructureIpsum instance, use the helper method trick to initialize it, and then simply use it to initialize the mesh:
SEMPotential(/* args */) : SI(ipsum_creator(args)), mesh(SI) {}
Initialization order of members is guaranteed (it's the order they appear in the class, the ordering in the initialization list has no effect).