I am honestly not sure how to google this even, and as my attempts have failed to do so, can you tell me how to write a prototype of constructor so that I can use it this way?
// MyClass.h
class Object;
class MyClass {
Object a;
Object b;
std::string c;
public:
MyClass(int, int, std::string&); // I do not know how to declare this properly
};
// so that I can write this:
MyClass::MyClass(int a, int b, std::string& c = "uninstantialised") : a(a), b(b) {
this->c = c;
}
// so that when I call the constructor like this:
Object a();
Object b();
MyClass mc(a, b);
// it doesn't produce an error when std::string argument is not specified.
Thanks!
Default arguments need to be specified in the declaration, not in the implementation. Furthermore, you should take the string by value, not by reference, and move it into the MyClass::c member:
public:
MyClass(int a, int b, std::string c = "uninstantialised");
// ...
MyClass::MyClass(int a, int b, std::string c)
: a(a), b(b), c(std::move(c))
{ }
Taking by value and using std::move() is not required, but recommended as it can be more efficient since it avoids copying the string in some cases.
I recommend renaming private data members to something that avoids the same name being used for something else. Here, c is both the private member as well as the constructor parameter. You should use something different for the members. Like a_, b_ and c_ for example. Appending an underscore is a popular way to name private data members.
I want to write little program with a few classes.
First class Number:
class Number
{
public:
virtual int compare(Number& a) = 0;
virtual string toString() = 0;
virtual void fillRandom() = 0;
};
Second class Rational that inherits from Number
class Rational:Number
{
public:
int l;
int m;
Rational(int a, int b)
{
this->l = a;
this->m = b;
}
int compare(Rational a){} // here is the problem
string toString(){}
void fillRandom(){}
};
I understand why I have this error, I have a pure virtual method int compare(Number& a) ,thus in all subclasses I must have same method.
But, if I change compare argument to Number it won't work without casting Number to Rational somewhere in compare.
Is there any way to do it without casting? Or what is the best way to do it?
First of all, you need to have some content in order to compare. What is it?
a) Can the Rational only be compared with the other Rational? or
b) somehow Value(Rational()) vs Value(OtherNumber())? where
class OtherNumber : public Number
{
// Some code here
}
If a, then you need to think why you put the compare() into the super class.
If b, then you need to abstract the other function, say
virtual long Value() const = 0;
and alter compare() so it works on the Value():
virtual int compare(const Number& a)
{
// something about Value() and a.Value();
}
BTW, normally the compare function is a const function. That is:
virtual int compare ( const Number& a ) const;
Also, remember to extend the Number with public, i.e.
class Rational : public Number
Otherwise you will lose polymorphic behavior.
You can use the below signature (both in base and derived classes) (keeping the virtual declaration in the base):
int compare(const Number* a){}
So basically the idea is to use pointers instead of references. This should work and you don't have to perform any kind of casting to call the compare method.
However, with the code above you still have to dynamically cast Number to Rational in the compare method body. Additionally, you have to take into account that it's possible to call a compare with any subclass of Number and maybe you are not interested in this behavior. So you have to added some checks to make sure that you are comparing against an incompatible class.
I have two classes which represent two different data types that can be converted back and forth. I want to have a constructor for each which takes an object of the other type so that I can more easily convert between the two, like so:
class A{
public:
A(B n){
//Do stuff converting n to type A
}
};
class B{
public:
B(A n){
//Do stuff converting n to type B
}
};
But it always fails to compile.
If you pass B by reference, you can use it as an incomplete type in A, with a forward declaration, like:
class B; // forward declaration
class A {
public:
A() = default;
A(B& n); // declare it here
};
class B {
public:
B() = default;
B(A n) {
//Do stuff converting n to type B
}
};
A::A(B& n) // define it here, B is fully visible now
{
//Do stuff converting n to type A
}
int main()
{
A a;
B b(a);
A another(b);
}
Note that you'd also need default constructors for at least A or B, as otherwise you cannot create an A without a B or the other way around. We also only declared the constructor in A, but defined it after B is fully visible (thanks #MattMcNabb for the comment). In this way, you'd be able to use any member of B in the constructor, since at that point B is fully visible.
The problem you are having is a common for beginners of C++ (or C for that matter).
The issue is that the signature A(B n) is seen by the compiler before the declaration of B is seen. But clearly, you cannot put B before A in the code, or you'd end up with the same type of situation.
This can be solved using forward declarations and references. My suggested default approach to this would be to declare these two entities as
class B;
class A {
public:
A(const B& n) {
// Do stuff converting n to type A
}
};
class B {
public:
B(const A& n) {
// Do stuff converting n to type B
}
};
I have three classes; their function definitions are in a sperate file.
I'm trying to construct an object with various parameters inside another class without using inline implementation.
class A{
public:
A(){}
};
class B{
public:
//takes in two ints, one reference to object, and a string
B(int x, int y, A &a, std::string s );
};
class C{
public:
//in the constructor, construct b_obj with its parameters
C();
private:
B b_obj;
};
How can I make the C constructor construct b_obj with its parameters of the int, the reference to an instance of A, and the string? I tried some methods but I get an error that complains about no match call to the b_obj constructor.
Use an initializer:
C() : b_obj(5, 6, A(), ""){}
This line technically won't work, though, because B's constructor takes an A&, so you can't bind a temporary to it. const A & if it's not being changed, or A if it is, would work out better if you don't have a non-temporary A to pass in.
You need to pass the relevant items to a constructor of object C, and then use an initializer.
class C {
public:
C(int x, int y, A& a, std::string s) : b_obj(x, y, a, s) {}
As a C# developer I'm used to running through constructors:
class Test {
public Test() {
DoSomething();
}
public Test(int count) : this() {
DoSomethingWithCount(count);
}
public Test(int count, string name) : this(count) {
DoSomethingWithName(name);
}
}
Is there a way to do this in C++?
I tried calling the Class name and using the 'this' keyword, but both fail.
C++11: Yes!
C++11 and onwards has this same feature (called delegating constructors).
The syntax is slightly different from C#:
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {}
};
C++03: No
Unfortunately, there's no way to do this in C++03, but there are two ways of simulating this:
You can combine two (or more) constructors via default parameters:
class Foo {
public:
Foo(char x, int y=0); // combines two constructors (char) and (char, int)
// ...
};
Use an init method to share common code:
class Foo {
public:
Foo(char x);
Foo(char x, int y);
// ...
private:
void init(char x, int y);
};
Foo::Foo(char x)
{
init(x, int(x) + 7);
// ...
}
Foo::Foo(char x, int y)
{
init(x, y);
// ...
}
void Foo::init(char x, int y)
{
// ...
}
See the C++FAQ entry for reference.
Yes and No, depending on which version of C++.
In C++03, you can't call one constructor from another (called a delegating constructor).
This changed in C++11 (aka C++0x), which added support for the following syntax:
(example taken from Wikipedia)
class SomeType
{
int number;
public:
SomeType(int newNumber) : number(newNumber) {}
SomeType() : SomeType(42) {}
};
I believe you can call a constructor from a constructor. It will compile and run. I recently saw someone do this and it ran on both Windows and Linux.
It just doesn't do what you want. The inner constructor will construct a temporary local object which gets deleted once the outer constructor returns. They would have to be different constructors as well or you would create a recursive call.
Ref: https://isocpp.org/wiki/faq/ctors#init-methods
C++11: Yes!
C++11 and onwards has this same feature (called delegating constructors).
The syntax is slightly different from C#:
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {}
};
C++03: No
It is worth pointing out that you can call the constructor of a parent class in your constructor e.g.:
class A { /* ... */ };
class B : public A
{
B() : A()
{
// ...
}
};
But, no, you can't call another constructor of the same class upto C++03.
In C++11, a constructor can call another constructor overload:
class Foo {
int d;
public:
Foo (int i) : d(i) {}
Foo () : Foo(42) {} //New to C++11
};
Additionally, members can be initialized like this as well.
class Foo {
int d = 5;
public:
Foo (int i) : d(i) {}
};
This should eliminate the need to create the initialization helper method. And it is still recommended not calling any virtual functions in the constructors or destructors to avoid using any members that might not be initialized.
If you want to be evil, you can use the in-place "new" operator:
class Foo() {
Foo() { /* default constructor deliciousness */ }
Foo(Bar myParam) {
new (this) Foo();
/* bar your param all night long */
}
};
Seems to work for me.
edit
As #ElvedinHamzagic points out, if Foo contained an object which allocated memory, that object might not be freed. This complicates things further.
A more general example:
class Foo() {
private:
std::vector<int> Stuff;
public:
Foo()
: Stuff(42)
{
/* default constructor deliciousness */
}
Foo(Bar myParam)
{
this->~Foo();
new (this) Foo();
/* bar your param all night long */
}
};
Looks a bit less elegant, for sure. #JohnIdol's solution is much better.
Simply put, you cannot before C++11.
C++11 introduces delegating constructors:
Delegating constructor
If the name of the class itself appears as class-or-identifier in the
member initializer list, then the list must consist of that one member
initializer only; such constructor is known as the delegating
constructor, and the constructor selected by the only member of the
initializer list is the target constructor
In this case, the target constructor is selected by overload
resolution and executed first, then the control returns to the
delegating constructor and its body is executed.
Delegating constructors cannot be recursive.
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};
Note that a delegating constructor is an all-or-nothing proposal; if a constructor delegates to another constructor, the calling constructor isn't allowed to have any other members in its initialization list. This makes sense if you think about initializing const/reference members once, and only once.
No, in C++ you cannot call a constructor from a constructor. What you can do, as warren pointed out, is:
Overload the constructor, using different signatures
Use default values on arguments, to make a "simpler" version available
Note that in the first case, you cannot reduce code duplication by calling one constructor from another. You can of course have a separate, private/protected, method that does all the initialization, and let the constructor mainly deal with argument handling.
Another option that has not been shown yet is to split your class into two, wrapping a lightweight interface class around your original class in order to achieve the effect you are looking for:
class Test_Base {
public Test_Base() {
DoSomething();
}
};
class Test : public Test_Base {
public Test() : Test_Base() {
}
public Test(int count) : Test_Base() {
DoSomethingWithCount(count);
}
};
This could get messy if you have many constructors that must call their "next level up" counterpart, but for a handful of constructors, it should be workable.
In Visual C++ you can also use this notation inside constructor: this->Classname::Classname(parameters of another constructor). See an example below:
class Vertex
{
private:
int x, y;
public:
Vertex(int xCoo, int yCoo): x(xCoo), y(yCoo) {}
Vertex()
{
this->Vertex::Vertex(-1, -1);
}
};
I don't know whether it works somewhere else, I only tested it in Visual C++ 2003 and 2008. You may also call several constructors this way, I suppose, just like in Java and C#.
P.S.: Frankly, I was surprised that this was not mentioned earlier.
This approach may work for some kinds of classes (when the assignment operator behaves 'well'):
Foo::Foo()
{
// do what every Foo is needing
...
}
Foo::Foo(char x)
{
*this = Foo();
// do the special things for a Foo with char
...
}
I would propose the use of a private friend method which implements the application logic of the constructor and is the called by the various constructors. Here is an example:
Assume we have a class called StreamArrayReader with some private fields:
private:
istream * in;
// More private fields
And we want to define the two constructors:
public:
StreamArrayReader(istream * in_stream);
StreamArrayReader(char * filepath);
// More constructors...
Where the second one simply makes use of the first one (and of course we don't want to duplicate the implementation of the former). Ideally, one would like to do something like:
StreamArrayReader::StreamArrayReader(istream * in_stream){
// Implementation
}
StreamArrayReader::StreamArrayReader(char * filepath) {
ifstream instream;
instream.open(filepath);
StreamArrayReader(&instream);
instream.close();
}
However, this is not allowed in C++. For that reason, we may define a private friend method as follows which implements what the first constructor is supposed to do:
private:
friend void init_stream_array_reader(StreamArrayReader *o, istream * is);
Now this method (because it's a friend) has access to the private fields of o. Then, the first constructor becomes:
StreamArrayReader::StreamArrayReader(istream * is) {
init_stream_array_reader(this, is);
}
Note that this does not create multiple copies for the newly created copies. The second one becomes:
StreamArrayReader::StreamArrayReader(char * filepath) {
ifstream instream;
instream.open(filepath);
init_stream_array_reader(this, &instream);
instream.close();
}
That is, instead of having one constructor calling another, both call a private friend!
If I understand your question correctly, you're asking if you can call multiple constructors in C++?
If that's what you're looking for, then no - that is not possible.
You certainly can have multiple constructors, each with unique argument signatures, and then call the one you want when you instantiate a new object.
You can even have one constructor with defaulted arguments on the end.
But you may not have multiple constructors, and then call each of them separately.
When calling a constructor it actually allocates memory, either from the stack or from the heap. So calling a constructor in another constructor creates a local copy. So we are modifying another object, not the one we are focusing on.
Would be more easy to test, than decide :)
Try this:
#include <iostream>
class A {
public:
A( int a) : m_a(a) {
std::cout << "A::Ctor" << std::endl;
}
~A() {
std::cout << "A::dtor" << std::endl;
}
public:
int m_a;
};
class B : public A {
public:
B( int a, int b) : m_b(b), A(a) {}
public:
int m_b;
};
int main() {
B b(9, 6);
std::cout << "Test constructor delegation a = " << b.m_a << "; b = " << b.m_b << std::endl;
return 0;
}
and compile it with 98 std:
g++ main.cpp -std=c++98 -o test_1
you will see:
A::Ctor
Test constructor delegation a = 9; b = 6
A::dtor
so :)