1) First Code
class A
{
public:
int i;
int b;
A(int temp){
i=temp;
A();
b=0;
}
A(){
b=0;
}
void display(){
printf("%d %d\n",i,b);//1 0
}
};
int main(){
A Aobj(1);
Aobj.display();
return 0;
}
Output: 1 0
2) Second Code
class A
{
public:
int i;
int b;
A(int temp) : i(temp), A(), b(0) {}//Error
A() : b(0) {}
void display(){
printf("%d %d\n",b,i);
}
};
int main()
{
A Aobj(1);
Aobj.display();
return 0;
}
I was expecting that both the codes will show same behavior and will produce an error as calling one constructor from the other in the same class is not permitted. It's not C++11.
So why does using the intializer list make a difference?
I compiled this codes in g++ 4.3.4 .
A(); is not doing what you think it does.
Replace it with double(); or char(); or any other type. Note that it works.
All you are doing is creating an anonymous additional instance of the type then throwing it away. It has no impact on this and will not do what you think it does.
The initializer list works in C++11 the way you would expect.
This has nothing to do with C++11 at all.
As pointed out by Yakk in the first case, you construct an anonymous member non recursively through a different constructor (the default constructor).
In case 'B'; you try to initialize from the initialzier list a member that doesn't exist. You don't have an instance of A or an A* existing within A to initialize.
Related
Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
I have this code:
i receive next error: A::A(int) candidate expect 1 argument, 0 provided but I cannot understand what the problem is.
#include <iostream>
using namespace std;
class A
{
int x;
public:
A(int i):x(i) {}
int get_x() const {return x;}
};
class B:public A
{
int *y;
public:
B(int i):A(i) {y=new int[i]; for(int j=0;j<i;j++) y[j]=1;}
B(B&);
int &operator[] (int i) {return y[i];}
};
B::B(B&a)
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
ostream& operator<<(ostream& o, B a)
{
for(int i=0;i<a.get_x();i++) o<<a[i];
return o;
}
int main()
{
B b(5);
cout<<b;
return 0;
}
Because A does not have a constructor that takes 0 arguments you need to explicitly call the constructor with arguments provided from any class constructor that inherits from A, which is B in this case.
In your first constructor:
B(int i):A(i) {y=new int[i]; for(int j=0;j<i;j++) y[j]=1;}
You are doing this well by calling A(i).
But in your second constructor:
B::B(B&a)
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
There is no call to A's constructor and thus you get an error since the compiler doesn't know how to create an A object, you probably meant to do :
B::B(B&a) : A(a.get_x())
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
Your second B constructor B::B(B&a) implicitly tries to construct the base class A using its default constructor, which is not defined.
You may explicitly call the A(int) constructor, i.e.:
B::B(B&a)
: A(a.get_x())
{
...
The problem is that when you declare an object of type B you also sort need to construct an instance of A.
In B::B(B&a) you do not explicitly call any constructor for A, so the compiler try to call the one with no parameters A::A(), but it fails since it is not declared.
You have to either declare a A::A() in A or explicitly call one of the available constructors in A from B's constructror.
Note that A::A() could be automatically generated by the compiler, and is called default constructor. Read more about it here
Class A
{
public:
A();
A(int x , int y);
Private:
int x;
int y;
}
Class B
{
public:
B();
A getApointerobject() const;
Private:
A *APointerObject;
int main()
{
B bObj;
cout << bObj.getApointerobject(); //i overloaded the << so that i can //output B objects but it crushes
}
//Class B implementation (This is where i struggle)
A getApointerobject() const {
return *getApointerobject;
}
In B::getApointerobject() you call it recursively. You should change to
A getApointerobject() const {
return *APointerObject;
}
Is B::APointerObject initialized before you call getApointerobject() method?
In getApointerobject you are trying to return the address of the method getApointerobject itself. I guess you code is not even compiling right now?
I guess you want to return your APointerObject
A B::getApointerobject() const {
return *this->APointerObject;
}
But be advised: Built in types, including simple pointers don't have a default constructor. So, since you don't initialise APointerObject in class Bs constructor, you would use a wild pointer. Which means you program would crash at runtime or worse (undefined behavior)
I don't think is a duplicate question. There are similar ones but they're not helping me solve my problem.
According to this, the following is valid in C++:
class c {
public:
int& i;
};
However, when I do this, I get the following error:
error: uninitialized reference member 'c::i'
How can I initialise successfully do i=0on construction?
Many thanks.
There is no such thing as an "empty reference". You have to provide a reference at object initialization. Put it in the constructor's base initializer list:
class c
{
public:
c(int & a) : i(a) { }
int & i;
};
An alternative would be i(*new int), but that'd be terrible.
Edit: To maybe answer your question, you probably just want i to be a member object, not a reference, so just say int i;, and write the constructor either as c() : i(0) {} or as c(int a = 0) : i(a) { }.
A reference must be initialised to
refer to something.
int a;
class c {
public:
int& i;
c() : i (a) {};
};
Apart from the sweet syntax, a key feature of references is that you are pretty sure that it always point to a value (No NULL value).
When designing an API, it forces user to not send you NULL.
When consuming an API, you know without reading the doc that NULL is not an option here.
References have to be initialized upon creation. Thus you have to initialize it when the class is created. Also you have to provide some legal object to reference.
You have to use the initializer in your constructor:
class c {
public:
c(const int& other) : i(other) {}
int& i;
};
Reference should be initialised either by passing data to constructor or allocate memory from heap if you want to initialize in default constructor.
class Test
{
private:
int& val;
std::set<int>& _set;
public:
Test() : val (*(new int())),
_set(*(new std::set<int>())) { }
Test(int &a, std::set<int>& sett) : val(a), _set(sett) { }
};
int main()
{
cout << "Hello World!" << endl;
Test obj;
int a; std::set<int> sett;
Test obj1(a, sett);
return 0;
}
Thanks
template<class T>
class AVLNode {
private:
T & data;
public:
AVLNode(T & newData) {
data = newData;
}
};
if every assignment creates a temporary to copy the object into lvalue, how can you check to see in VC++ 8.0?
class E
{
int i, j;
public:
E():i(0), j(0){}
E(int I, int J):i(I), j(J){}
};
int main()
{
E a;
E b(1, 2);
a = b //would there be created two copies of b?
}
Edit:
Case 2:
class A
{
int i, j;
public:
A():i(0), j(0){}
};
class E
{
int i, j;
A a;
public:
E():i(0), j(0){}
E(int I, int J):i(I), j(J){}
E(const E &temp)
{
a = temp; //temporary copy made?
}
};
int main()
{
E a;
E b(1, 2);
a = b //would there be created two copies of b?
}
From your comment, you made it clear that you didn't quite understand this C++-FAQ item.
First of all, there are no temporaries in the code you presented. The compiler declared A::operator= is called, and you simply end up with 1 in a.i and 2 in a.j.
Now, regarding the link you provided, it has to do with constructors only. In the following code :
class A
{
public:
A()
{
s = "foo";
}
private:
std::string s;
};
The data member s is constructed using std::string parameterless constructor, then is assigned the value "foo" in A constructor body. It's preferable (and as a matter of fact necessary in some cases) to initialize data members in an initialization list, just like you did with i and j :
A() : s("foo")
{
}
Here, the s data member is initialized in one step : by calling the appropriate constructor.
There are a few standard methods that are created automatically for you if you don't provide them. If you write
struct Foo
{
int i, j;
Foo(int i, int j) : i(i), j(j) {}
};
the compiler completes that to
struct Foo
{
int i, j;
Foo(int i, int j) : i(i), j(j)
{
}
Foo(const Foo& other) : i(other.i), j(other.j)
{
}
Foo& operator=(const Foo& other)
{
i = other.i; j = other.j;
return *this;
}
};
In other words you will normally get a copy constructor and an assignment operator that work on an member-by-member basis. In the specific the assignment operator doesn't build any temporary object.
It's very important to understand how those implicitly defined method works because most of the time they're exact the right thing you need, but sometimes they're completely wrong (for example if your members are pointers often a member-by-member copy or assignment is not the correct way to handle the operation).
This would create a temporary:
E makeE( int i, int j )
{
return E(i, j);
}
int main()
{
E a;
a = makeE( 1, 2 );
E b = makeE( 3, 4 );
}
makeE returns a temporary. a is assigned to the temporary and the assignment operator is always called here. b is not "assigned to", as it is being initialised here, and requires an accessible copy-constructor for that to work although it is not guaranteed that the copy-constructor will actually be called as the compiler might optimise it away.