Return class object with member variable - c++

Why the function test() works even I'm not returning a Base class ? What happens with the compilation ? Can someone explain me ?
#include <iostream>
class Base {
public:
Base(){}
Base(int val): _val(val){};
~Base(){};
Base test(int n){
return (n);
}
int &operator *() { return (_val); };
private:
int _val;
};
int main()
{
Base base;
Base a;
a = base.test(42);
std::cout << *a << std::endl;
return (0);
}

You declared a constructor that takes in an int, and you declared that test(int n) should always return a Base class. The compiler knows that in order to create a Base object you need either nothing (default constructor) or an int, so it creates an object using the constructor that takes an int an returns that.
If you wanted to, you could be explicit about it and do something like the following and get the exact same behaviour:
Base test(int n){
return Base(n);
}
In short, n is implicitly cast to a Base object, as you declared a constructor that requires only an int.

Related

how to pass pointer to constructor in c++

have a derived class that needs to take a pointer as a constructor for the base class.
how do you do this in c++, i tried it but it gave me a bug.
#include <iostream>
using namespace std;
class Base {
protected:
int *num;
public:
Base(int *num);
virtual void print();
};
Base::Base(int *num){
this->num = num;
};
class Derived : public Base {
public:
Derived(int *num) : Base(*num);
void print();
};
Derived::print(){
cout << "int value : " << *(this->num);
};
int main(){
int num = 5;
int *p = &num;
Derived derived(p);
derived.print();
return 0;
}
In the constructor initializer list of Derived you have to write Base(num) instead of Base(*num) as shown below:
Derived(int *num): Base(num)
{
//code here
}
Note that you don't have to dereference the pointer num which you were doing while using it in the constructor initializer list. When you dereference num, you got an int. And so you were passing that int to the Base constructor.

Manually calling constructor of base class outside initialization list

I have a Derived class whose constructor has to populate the fields of a struct that is passed as an argument to the constructor of the Base class. I want to be able to name the fields of the struct that I am populating, to keep my code future-proof (i.e.: resistant to addition and/or reordering of the members of MyStruct).
Note that struct MyStruct has default values, so it cannot be initialised with named fields directly in the initialization list (e.g.: Base({.a = a, .b = b}) does not work). Also, in my case, Base's copy constructor is deleted. Also, I am using C++ 11.
The solution I came up with uses the placement new operator to manually call the constructor of the Base class on the memory pointed to by this. To achieve this I also had to add a protected default constructor to my Base class. Are there any possible downsides to this approach and/or could anyone suggest a better method?
#include <iostream>
struct MyStruct
{
int a = 0;
int b = 1;
};
class Base
{
public:
Base(MyStruct str){
std::cout << "a: " << str.a << ", b: " << str.b << "\n";
}
Base(Base&&) = delete; // no copy constructor
protected:
Base(){ // dummy, does exactly nothing.
// it only exists to be called by
// the derived class's constructor
}
private:
int amember;
};
class Derived : public Base
{
public:
Derived(int a, int b)
{
MyStruct str;
str.a = a;
str.b = b;
new (this) Base(str);
}
private:
int anothermember;
};
int main()
{
MyStruct str;
str.a = 10;
str.b = 20;
Base b(str);
Derived d(10, 20);
return 0;
}
edit: added mention that Base cannot be copied, made explicit that Base::Base() does exactly nothing.
Use a helper function instead like
class Derived : public Base
{
public:
Derived(int a, int b) : Base(make_mystruct(a, b)), anothermember(some_value) {}
private:
int anothermember;
static MyStruct make_mystruct(int a, int b) { return MyStruct(a, b); }
};
I would just like to add that this could be a good opportunity to use IILE, Immediately Invoked Lambda Expression, if you for whatever reason don't want a named helper function:
class Derived : public Base
{
public:
Derived(int a, int b) : Base{[](){
MyStruct str;
str.a = a;
str.b = b;
return str; }()}
{}
};
The benefit is that you will not need to construct the class and it's members only once, since you do everything in the initialization list. If you in the future add non-trivial members to Base, you will be will not have to pay for double initialization.

Access private data member of class from unrelated class in C++ converter constructor

In the code given below, to access private data member of B we can use member function of class B and return the data member, assign that to the data member of A within the constructor (converter function). But I am unable to do so. Please suggest some help. Other way can be making Class A friend of B but there is need for accessing by constructor.
#include <iostream>
using namespace std;
class B
{
int i_;
public:
B(int i = 3) : i_(i) {}
int give() { return i_; }
};
class A
{
int i_;
public:
A(int i = 0) : i_(i) { cout << "A::A(i)\n"; }
A(const B &b1) : i_(b1.i_) {} // Type casting using constructor
int display() { cout << i_; }
};
int main()
{
A a;
B b; // object is constructed
a = static_cast<A>(b); // B::operator A(), converting data member of class B to class A
a.display();
return 0;
}
It's not enough to follow #StoryTeller's advice, you also need to change constructor of A to use proper 'getter' method so that you stop accessing private member:
A(const B &b1) : i_(b1.give()) {}
Your problem is const correctness. int give() is a non-const member function, which can only be called on non-const objects. However const B &b1 is a reference to a const object.
Since you don't modify the B object when returning the value of the integer, make your code const correct by const qualifying the member function:
int give() const { return i_; }
And now the A c'tor isn't attempting an illegal operation.

Not able to call base class constructor from dericed class with parameter in c++

I have below scenario in c++ within DEV c++
class base{
int i=0;
public:
base(){
cout<<"base default constructor"<<endl;
}
base(int i){
cout<<"base with int"<<endl;
}
};
class derive : public base{
int j;
public:
derive(){
cout<<"derive default";
}
derive(int i){
int k=5;
base(k);//////error
cout<<"derived with int "<<i<<endl;
}
void fun(int i){
cout<<"finction "<<i<<endl;
}
};
int main()
{
derive d(9);
}
After running following error is coming
[Error] conflicting declaration 'base k'
[Error] 'k' has a previous declaration as 'int k'
Why this error is coming.
Its working fine when i call base(5) with any parameter except declared in derived constructor.
Thanks in advance.
If you call the base constructor within the derived class on the implicit parameter, it needs to be done in the field initialization list like so:
derive(int i) : base(i) {
cout<<"derived with int "<< i <<endl;
}
live demo
#include <iostream>
using namespace std;
class base{
public:
base(){
cout<<"base default constructor"<<endl;
}
base(int i){
cout<<"base with int "<<i<<endl;
}
};
class derive : public base{
public:
int j;
int k;
derive(){
cout<<"derive default\n";
}
derive(int i){
k=5;
base(this->k);//////error
cout<<"derived with int "<<i<<endl;
}
void fun(int i){
cout<<"finction "<<i<<endl;
}
};
int main()
{
derive p(10);
}
There are two interpretations of what base(k) could be:
it could be a the creation of temporary
it could be a variable declaration: the variable name can be in parenthesis
Out of these two choices, the compiler uses the second one: if something can be either a declaration or an expression, the declaration is chosen. This is related to the most vexing parse although it isn't that. The effect is that in your use base(k); tries to define a variable named k of type base.
You can disambiguate the meaning using one of
(base(k));
base{k};
If base also had a constructor taking an std::initializer_list<int> these two can have different meanings.
In main()
base b(3);
derive d(9);
base b1(2);
//create explicit object and pass integer parameter.then try
also pass particular integer value in derive->base.
in derive
base(8);
And always print the value of variable acting weirdly in a program

How to use a copy constructor with a base class?

I'm confused about base classes and copy constructors.
Say I have a class
class A {
public:
A(int m) : m(m) { return; }
virtual ~A() { return; }
int m;
}
And a class that inherits this
class B : public A {
public:
B(int n, int m) : A(m), n(n) { return; }
vitual ~B() { return; }
int n;
}
When I copy class B, how do I ensure that the m value in class A is copied as well?
The default copy constructor will copy all of the member variables, no matter whether they reside in the base class or a derived class.
If you create your own copy constructor for class B you will need to copy the class A members yourself, or better yet use the copy constructor for class A in the initializer list.
class B : public A {
public:
// ...
B(const B & b) : A(b), n(b.n) {}
// ...
};
The base copy constructor will be called before the derived copy constructor automatically. It's the same as for a regular constructor. (More accurately, the base constructor is called by derived initialization list before derived constructor continues). In your case, the default copy constructors are sufficient.
Be careful, however, that you do not copy a B into an A (search object splicing).
This code is your code just copy constructors are added with a class:
#include <iostream>
using namespace std;
struct Int
{
Int ()
{
}
Int(const Int&)
{
cout<< "Int copied" "\n";
}
};
class A
{
Int m;
public:
A(Int m) : m(m)
{
}
virtual ~A()
{
}
};
class B : public A
{
Int n;
public:
B(Int n, Int m) : A(m), n(n)
{
}
virtual ~B()
{
}
};
void f(B)
{
}
int main()
{
Int m,n;
B b(m,n);
cout<< "\n" "start:" "\n";
f(b);
cout<< "end";
}
Ubuntu Qt Creator Output says both are copied.
One can think there's a hidden member with type B in A and this hidden member can be initialized or copied as a usual member as in the above program with:
B(Int n, Int m) : A(m), n(n)
You should not return from a constructor/destructor, not even void.