#Using constructors of the base class from derived

80 messages · Page 1 of 1 (latest)

ashen rootBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.

silver birch
#

What's the problem?

#

If you want to inherit from dot, you can do this only 1 time afaik

void swallow
#

No no is there a better method than this one u showed me

#

Like

#

hmm

#

This one here creates two additional dots which would lead to using destructor twice more?
So can we avoid it somehow and use it only here would be 3 times?

silver birch
#

A Circle usually has only 1 mid-point (dot), right?

mental wadi
#
class Base
{
public:
       Base(int x) : a{ x } {}
private:
       int a{};
};

class Derived : public Base
{
public: 
       Derived(int a, int b) 
           : Base{ a }
           ,  x { b } {}
private:
        Int x{};
};
void swallow
#

yess, but im not talking about how many dots does circle have, instead how can i avoid creating two additional dots just to init A and B

severe moat
#

you mean initializer lists?

silver birch
#

You can probably use std::move() to transfer ownership of the dots

mental wadi
void swallow
#

im not eaxctly sure what this list is but let me explain it as much as i can!
If i were to have:
** dot( int, int ) *

I wouldnt make
int x = 5;
int y = 3:

just so i can say

dot A( x, y );

instead you would use A's constructor and say
dot A( 5 , 3 )?

So same here, want to use A's constructor directly from main.

#

this one is the closest one to what im trying to achieve

mental wadi
#

What I can understand is you are confused in OOP

void swallow
#

it just feels a bit strnage saying
Circle c(
dot(100.0,150.0),
dot(200.0,300.0)
);

#

yes

mental wadi
#

Ok

#

Let me be clear

#

You want to initialise the dot in A's constructor without using dot's constructor.
Am I right ?

void swallow
silver birch
mental wadi
mental wadi
void swallow
#

what im trying to achieve somehow if its possible i dont know it is:



class dot {
    float x,y;
public:
    dot(float x = 0.0, float y = 0.0) : x(x), y(y) {};
};

class Circle {
protected:
    float p;
    dot A, B;
public:
    Circle( dot a, dot b, float r = 0.0 ) : A( a ), B( b ), p(r) {};
};

int main(int argc, char *argv[]) {
   // dot a(100.0,150.0);
   // dot b(200.0,300.0);
    Circle c(a( 100.0, 50.0 ), b( 200.0, 300.0 ) );
}


mental wadi
#

You can use it like this also --

Circle a({100, 200}, {100, 200})
Circle a(dot(100, 200), dot(100,200))
void swallow
#

Circle a(dot(100, 200), dot(100,200))

this one is hard for me to understand

silver birch
#

Unfortunately C++ has no named parameters

void swallow
#

how come its okay to do dot(smth.) instead of a(smth.)

silver birch
#

a is no type

#

dot is a class

void swallow
#

Circle( dot a, dot b, float r = 0.0 )
U call it by the class and not the variable name

#

which feels weird to me

#

but its fine ill get used to it eventually

#

anyway

#

thanks

mental wadi
#

You can use that way if you want.

silver birch
void swallow
#

!solved

ashen rootBOT
#

Thank you and let us know if you have any more questions!

silver birch
#

@mental wadi Do you know why the destructor is called 4 times? ```c++
#include <iostream>
#include <utility>

class dot {
float x,y;
public:
dot(float x, float y) : x(x), y(y) {};
virtual ~dot() {
std::cout << "dot.destructor" << std::endl;
}
};

class Circle {
protected:
float p;
dot A, B;
public:
Circle( dot&& a, dot&& b, float r = 0.0 ) : A( std::move(a) ), B( std::move(b) ), p(r) {};
};

int main(int argc, char *argv[]) {
Circle c(
dot(100.0,150.0),
dot(200.0,300.0)
);
}

#

I think that is what @void swallow wanted to avoid

mental wadi
silver birch
#

I get this output: ```
dot.destructor
dot.destructor
dot.destructor
dot.destructor

#

So it's 4 times instead of the desired 2

astral tangleBOT
#
Program Output
dot.destructor
dot.destructor
dot.destructor
dot.destructor
silver birch
#

I'm new to modern C++ for 3 days only, sorry. Did some C++98 15 years ago.

mental wadi
silver birch
#

My understanding is that std::move() transfers the ownership, but somehow 4 dot() get constructed

#

Can we avoid that somehow?

mental wadi
#

When you are calling Circle(dot( ... ), dot( ... )) You are creating two temporary dots which are getting copied into the two dots inside Circle. And then those two temporary are destroyed after getting copied. Destructor count = 2.
Then the actual member variable inside Circle in which you copied are getting destroyed when Circle is getting destroyed. Destructor count = 2.

Which is why dot's destructor is getting called twice.

silver birch
#

I tried to avoid that using std::move()

#

Looks like std::move() does not what I think

mental wadi
#

You cannot avoid it.

#

Because you need something to copy. Whether it be permanent or temporary object it needs to get constructed. And if it temporary then it will gets destroyed when required automatically...

#

The summary is whether it be temporary or permanent if you construct it, it will be destroyed at some point

silver birch
#

Got it now, std::move() works fine with pointer transfer

#
#include <iostream>
#include <utility>

class dot {
    float x,y;
public:
    dot(float x, float y) : x(x), y(y) {};
    virtual ~dot() {
        std::cout << "dot.destructor" << std::endl;
    }
};

class Circle {
protected:
    float p;
    dot *A, *B;
public:
    Circle( dot* a, dot* b, float r = 0.0 ) : A( std::move(a) ), B( std::move(b) ) , p(r) {
    };
    virtual ~Circle() {
        delete A;
        delete B;
        std::cout << "Circle.destructor" << std::endl;
    }
};

int main(int argc, char *argv[]) {
    Circle c(
        new dot(100.0,150.0),
        new dot(200.0,300.0)
    );
}
astral tangleBOT
#
Program Output
dot.destructor
dot.destructor
Circle.destructor
silver birch
#

Okay, thanks for your time @mental wadi!

mental wadi
silver birch
#

I'm moving ownership using std::move() 🤷‍♂️

mental wadi
#

Because if you allocate something with new then you are responsible to free that memory using delete. C++ doesn't do that for you

mental wadi
#

Do you know what it does ?

silver birch
#

"std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object."

#

I'm moving ownership of the 2 new dot() into Circle and delete them in the Circle destructor

mental wadi
#

std::move casts an lvalue into rvalue. Which means std::move moves the resources inside an object. In your case you allocated memory using new, then moves the resources from that memory, but you did not deallocate that memory and there you got memory leak

silver birch
#

Looks good to me, as expected: ```c++
#include <iostream>
#include <utility>

class dot {
float x,y;
public:
dot(float x, float y) : x(x), y(y) {};
virtual ~dot() {
std::cout << "dot.destructor" << std::endl;
}
};

class Circle {
protected:
float p;
dot A, B;
public:
Circle( dot
a, dot
b, float r = 0.0 ) : A( std::move(a) ), B( std::move(b) ) , p(r) {
};
virtual ~Circle() {
delete A;
delete B;
std::cout << "Circle.destructor" << std::endl;
}
};

int main(int argc, char *argv[]) {
auto a = new dot(100.0,150.0);
auto b = new dot(200.0,300.0);

Circle c( a, b );

//delete a;
//delete b;

}

mental wadi
silver birch
#

Thanks! 👍

mental wadi
#

If you are taking rvalue reference in function. Then you can call the constructor like this --

Circle a(std::move(dot{100, 200}), std::move(dot{100, 200}))

#

That will still call the destructor

#

If you are wondering why destructor is not getting called with pointers. It's because those dynamically allocated objects are not getting destroyed at the end of the function.