Creating a default constructor for a stack - c++

I am currently working on a project for class that requires us to implement a stack for integer use as a calculator. I am having problems with my default constructor and am wondering what I am missing.
OperandStack(int stackSize)
{
if (stackSize<=0)
{cout<<"Must be positive"<<endl;}
this->capacity=capacity;
s =new double[stackSize];
t=0;
}
Thanks for your help.

" I am having problems with my default constructor and am wondering what I am missing."
A default constructor takes no parameters, or declares default values for all of them. To cite from the linked reference documentation
Default constructors
A default constructor is a constructor which can be called with no arguments (either defined with an empty parameter list, or with default arguments provided for every parameter).
Thus your implementation should look like:
class OperandStack {
public:
OperandStack(int stackSize = 10)
// ^^^^ declare a default value
// Better use a member initializer list, instead of initializing claas
// members inside the constructor's body:
: capacity(stackSize), s(new double[stackSize]), t(0) {
if (stackSize<=0) {cout<<"Must be positive"<<endl;}
// ^^^^ Better use an exception instead of this
// output statement (it's OK for basic debugging)
}
};

Related

C++ : What is wrong with my class constructors ? (no default constructor exists &/or conflicting declaration)?

Trying to write a simple exponential filter class, self contained in a .h file.
I'm getting these errors:
no default constructor exists for class "ExpoFilter"
conflicting declaration 'ExpoFilter alpha_temp'
I don't understand the problem, I have 2 constructors, one for an int type parameter and one for a float type parameter. Isn't that enough to be considered 2 different function signatures?
I am also calling the first constructor from within the second one, which I've done successfully in the past. Also tried proper full .cpp + .h file without success.
So what is wrong?
Here is the code:
/*
Exponential filter, a.k.a exponential moving average, object Class
*/
#ifndef ExpoFilter_h
#define ExpoFilter_h
class ExpoFilter
{
// user-accessible "public" interface
public:
// Constructors
ExpoFilter::ExpoFilter(float alpha){
_alpha = alpha;
_alpha2 = 1.0f - _alpha;
}
ExpoFilter::ExpoFilter(int N){
float alpha_temp = 2.0f / (N + 1);
ExpoFilter(alpha_temp);
}
ExpoFilter::operator float(){
return _value;
}
float ExpoFilter::operator=(float newValue)
{
return NewValue(newValue);
}
float ExpoFilter::NewValue(float newValue){
_value = newValue * _alpha + _value * _alpha2;
return _value;
}
// library-accessible "private" interface
private:
float _alpha;
float _alpha2;
float _value;
};
#endif
The problem is that since you have a parameterized constructor for your class ExpoFilter, the compiler will not synthesize the default constructor ExpoFilter::ExpoFilter() by itself. This means that if you want to create/construct an object of class ExpoFilter using the default constructor, say by writing ExpoFilter alpha_temp;, then the compiler will produce error because there is no default constructor.
To solve this you must add a default constructor for your class as shown below:
class ExpoFilter
{
//other code here as before
//default constructor that uses constructor initializer list
ExpoFilter() : _alpha(0), _alpha2(0), value(0)
{
}
}
Now, when you wrote:
ExpoFilter(alpha_temp); //this creates a temporary object named alpha_temp using the default constructor
The above statement creates an object of type ExpoFilter named alpha_temp using the default constructor. But since the compiler did not synthesize a default ctor, you will get the mentioned error.
If your intention was to call the parameterized constructor instead of default constructor then you could change the above statement to:
ExpoFilter(2.0f / (N + 1));
"Default constructor" in this context means a constructor that takes no arguments, i.e.
ExpoFilter() {...}
You have a constructor that takes an int argument, and a constructor that takes a float argument, but no constructor that takes no arguments. So code like this:
ExpoFilter alpha_temp;
... can't compile because the compiler doesn't know how to construct the object with no argument supplied.
Btw, this line:
ExpoFilter(alpha_temp);
.... is not calling a constructor-method on your object; rather it is constructing a second (temporary/anonymous) ExpoFilter object that is created on the stack and then immediately destroyed -- probably not what you intended. (in particular, that line won't change the state of your original ExpoFilter object!). If you want to delegate to another constructor-method from within your constructor (and you are compiling with C++11 or newer) you'll need to call the other-constructor from your constructor's initializer-list instead:
ExpoFilter::ExpoFilter(int N)
: ExpoFilter(2.0f / (N + 1))
{
// ...
}

Base/Default Constructor vs Constructor Initialization list

I read a few different topics on these forums and I'm not getting a clear answer on it.
I have two questions, what is the difference between a default/base construct and a construct initialize list? They look the same to me, here are my examples. Do I have them commented correctly as well as what they are?
//In my .h file:
class Complex {
public:
Complex();
Complex(double, double);
private:
double real;
double imag;
};
//In my implementation file:
Complex::Complex() :real(NULL), imag(NULL) // initialization list
{
}
Complex::Complex(double inReal, double inImag) // default constructor
{
real = inReal;
imag = inImag;
}
I have two questions, what is the difference between a default/base construct and a construct initialize list?
A default constructor is a constructor that will be invoked when you create an object but don't specify any constructor arguments. For example, all these variables will be initialised by a call to the default constructor:
Complex myComplex1;
Complex myComplex2();
Complex myComplex3{};
Some other constructors do require arguments, so they're not default constructors.
In the implementation of any constructor (whether a default constructor or not) for an object with bases or member variables or constants, you can use an initialisation list to construct/initialise those bases or members.
They look the same to me, here are my examples. Do I have them commented correctly as well as what they are?
You didn't have them commented correctly. A fixed version is:
Complex::Complex() // default constructor as it does not require args
: real{}, imag{} // initialization list: sets both to 0.0
{ }
Complex::Complex(double inReal, double inImag) // NOT a default constructor
// as it requires arguments
: real(inReal), imag(inImag) // initialisation list
{
// real = inReal; // set in the initialisation list instead
// imag = inImag;
}
The non-default constructor above is invoked when you create an object while specifying matching constructor arguments:
Complex myComplex4(3.1, 2);
Complex myComplex5{-2.3, 2.7};
It's a good idea to preferentially use an initialisation list to construct your bases and set your members: otherwise at best they'll be default initialised then assigned to, which can be less efficient, but for references and constants you simply have to use an initialisation list.
It is possible to create a default constructor with arguments with default values:
Complex(double inReal = 0.0, double inImag = 0.0)
: real(inReal), imag(inImag)
{ }
This single constructor can reasonably replace both the constructors in your code.
In this case,
Complex::Complex() : real(NULL), imag(NULL)
{
}
would be your default constructor, because it is the one here that has no parameters.
An initializer list is what you see following your default constructor's name, being
:real(NULL), imag(NULL)
This is a list of member initializations that take place upon calling the default constructor Complex::Complex()
As an aside, NULL is a value meant to represent a pointer that does not point to any valid addressable memory location. It's not exactly applicable to double types.

Can't initialize field outside initializer list

I'm having trouble with something that seems very easy, so I must be overlooking something.
I need to construct a class that has a field that is also a class (non-POD). The class of the field has a default constructor and a "real" constructor. The thing is that I really can't construct the field in the initializer list, because in reality the constructor has a parameter that is a vector which needs a somewhat complex for loop to fill.
Here is a minimal example that reproduces the problem.
ConstructorsTest.h:
class SomeProperty {
public:
SomeProperty(int param1); //Ordinary constructor.
SomeProperty(); //Default constructor.
int param1;
};
class ConstructorsTest {
ConstructorsTest();
SomeProperty the_property;
};
ConstructorsTest.cpp:
#include "ConstructorsTest.h"
ConstructorsTest::ConstructorsTest() {
the_property(4);
}
SomeProperty::SomeProperty(int param1) : param1(param1) {}
SomeProperty::SomeProperty() : param1(0) {} //Default constructor, doesn't matter.
But this gives a compile error:
ConstructorsTest.cpp: In constructor 'ConstructorsTest::ConstructorsTest()':
ConstructorsTest.cpp:4:19: error: no match for call to '(SomeProperty) (int)'
the_property(4);
^
It gives no suggestions like it usually would of what functions could have been intended instead.
In the above example I would just initialize the_property in the initializer list, but in reality the 4 is actually a complex vector that needs to be generated first, so I really can't. Moving the_property(4) to the initializer list causes the compilation to succeed.
Other similar threads mention that the object must have a default constructor, or that it can't be const. Both requirements seem to have been met, here.
You can't initialize data member inside the constructor's body. (the_property(4); is just trying to invoke the_property as a functor.) You can only assign them like:
ConstructorsTest::ConstructorsTest() {
the_property = ...;
}
but in reality the 4 is actually a complex vector that needs to be generated first
You can add a member function which generate the necessary data, and use it to initialize the data member in member initializer list. e.g.
class ConstructorsTest {
...
static int generateData();
};
int ConstructorsTest::generateData() {
return ...;
}
ConstructorsTest::ConstructorsTest() : the_property(generateData()) {
}
You cannot initialize a variable twice.1 When your constructor has started, all member subobjects will have been constructed. If you do not provide a member initializer in the constructor, or a default member initializer in the class definition, then it will perform default initialization. Regardless of what form it takes, you can't construct it again.
Complex multi-statement initialization is best done via a lambda function:
ConstructorsTest::ConstructorsTest()
: the_property( []{ /* Do Complex Initialization */}() )
{
}
1: Well... you can, but not like that. And you really shouldn't for cases as simple as this.

Default constructor for struct with Long and pointer

I am in the process of learning c++.
I have a struct like this:
struct Info {
const Long rate;
A* ptr;
}
I have a constructor which takes all the arguments as its parameters to initialize the struct. However, this struct is part of another class which will be serialized using boost serialization. In order to serialize that class I would need a default constructor for this struct. However, when I try to write a default constructor such as
Info () {
}
I get an error C2758 that the member rate should be initialized in the constructor.
How to get a default constructor for such a struct which I can use to serialize my class.
You need to initialize the constant value, so:
Info () : rate(0) {
}
The error is probably due to the fact that your Long class does not have a default constructor either.
There are two ways of fixing this:
Add a default constructor to Long, or
Add rate to the initialization list of Info's constructor.
You can see the msdn documentation for C2758 for a description of the error.
In basic term's, a const variable must be initialised in all constructors. The compiler enforces that any built in type or pointer member that is const must be initialised when the object is constructed, as you won't get a chance to give it a meaningful value after construction ( if you could change it after it was created, how is it const ? ).
Also, as a general rule of thumb, it is always a good idea to initialise members that don't have a default constructor ( built in types, pointers, and objects without default constructors ) to something, in all your class constructors. Otherwise they will either be initialised to some random value ( primitives or pointers ), or you will get a compile error ( objects without default constructors ).
Info()
: rate(0)
, ptr(nullptr)
{
}
If you are assigning values to some of your parameters from constructor arguments, don't forget to assign a value to the other members as well.
Info( Long rate)
: rate( rate )
, ptr(nullptr)
{
}
try this :
struct Info {
const Long rate;
A* ptr;
Info():rate(0){} // as Matthew guessed, call the correct Long constructor
// or define a default constructor for Long
};

default constructor that has the option to take in a parameter?

Is it possible to have 1 constructor have the option of being a default constructor if a parameter is not passed in.
Example, instead of having 2 constructors, where 1 is the default constructor and another is a constructor that initializes numbers passed in, is it possible to only have 1 constructor that if a value is passed in, set that value to a member function, and if no value is passed in, set the member function to a number.
example:
WEIGHT.H file:
class Weight
{
public:
Weight() { size = 0; }
Weight(int a) : size(a) {}
int size;
};
MAIN.CPP file:
int main(void)
{
Weight w1;
Weight w2(100);
}
I've been working on different school projects and they all require to have different types of constructors, and i'm wondering if there is a way to only have it once so it saves time.
Thanks for the help.
Yes, a constructor parameter may have a default argument, just like other functions can. If all of the parameters of a constructor have default arguments, the constructor is also a default constructor. So, for example,
class Weight
{
public:
explicit Weight(int a = 0) : size(a) { }
int size;
};
This constructor may be called with a single argument or with no arguments; if it is called with no arguments, 0 is used as the argument for the a parameter.
Note that I've also declared this constructor explicit. If you have a constructor that may be called with a single argument, you should always declare it explicit to prevent unwanted implicit conversions from occurring unless you really want the constructor to be a converting constructor.
(If you aren't familiar yet with converting constructors or implicit conversions, that's okay; just following this rule is sufficient for most of the code you'll ever write.)
Yes its possible as suggested by James but as you know if you are not defining the Default constructor the compiler would take over the definition part if you have not provided any constructor definition.
Its not an issue as such but its a better practice to define the Default constructor for proper initialization of values.
Google C++ Style guide also recommends it.