move derived obj d to derived dd, but match base's move constructor, do not match derived's constructor
// base class
class base {
int x;
public:
base() = default;
base(base && b) {
x = b.x;
}
};
// derived struct
struct derived : public base {
int y;
derived(int d) {
y = d;
}
derived() = default;
};
int main()
{
derived d{1};
derived dd = std::move(d);
spdlog::info(dd.y); // => 1
return 0;
}
I do not know why dd.y will be 1, not 0 ?
how d.y copied to dd.y struct ?
Related
How to convert two parent pointers in c++?
This is the code.
// base class
class B {
public:
virtual ~B() {};
// other code
};
class A {
public:
virtual ~A() {};
// other code
};
// child class
class C1 : public A, B {
public:
virtual ~C1() {};
// other code
};
class C2 : public A, B {
public:
virtual ~C2() {};
// other code
};
// ...other C class
There is a std::vector<std::shared_ptr<A>> which items point to instance C1 or C2 ...Cn.
Does anyone know how to convert the vector to a std::vector<std::shared_ptr<B>>?
Your code has typos. Missing public in inheritance of B when defining C<x> breaks stuff.
After this is fixed sidecast does the job as it should:
dynamic_cast conversion - cppreference.com
b) Otherwise, if expression points/refers to a public base of the most derived object, and, simultaneously, the most derived object has an unambiguous public base class of type Derived, the result of the cast points/refers to that Derived (This is known as a "sidecast".)
// base class
class B {
public:
virtual ~B() { }
};
class A {
public:
virtual ~A() { }
};
class C1 : public A, public B {
public:
virtual ~C1() { }
};
class C2 : public A, public B {
public:
virtual ~C2() { }
};
TEST(SideCast, sigleItemCast)
{
C2 x;
A* a = &x;
auto b = dynamic_cast<B*>(a);
ASSERT_THAT(b, testing::NotNull());
}
TEST(SideCast, sideCastOfVectorContent)
{
std::vector<std::shared_ptr<A>> v { std::make_shared<C1>(), std::make_shared<C2>() };
std::vector<std::shared_ptr<B>> x;
std::transform(v.begin(), v.end(), std::back_inserter(x),
[](auto p) { return std::dynamic_pointer_cast<B>(p); });
ASSERT_THAT(x, testing::Each(testing::NotNull()));
}
Live demo
I came across this code in a past exam:
#include <iostream>
class cls1
{
protected:
int x;
public:
cls1()
{
x = 13;
}
};
class cls2 : public cls1
{
int y;
public:
cls2()
{
y = 15;
}
int f(cls2 ob)
{
return (ob.x + ob.y);
}
};
int main()
{
cls2 ob;
std::cout << ob.f(ob);
return 0;
}
This works just fine and outputs 28. The problem is, it seems to contradict with this code (found in another exam):
#include <iostream>
class B
{
protected:
int x;
public:
B(int i = 28)
{
x = i;
}
virtual B f(B ob)
{
return x + ob.x + 1;
}
void afisare()
{
std::cout << x;
}
};
class D : public B
{
public:
D(int i = -32)
: B(i)
{
}
B f(B ob)
{
return x + ob.x - 1;/// int B::x is protected within this context
}
};
int main()
{
B *p1 = new D, *p2 = new B, *p3 = new B(p1->f(*p2));
p3->afisare();
return 0;
}
It's the same type of hierarchy, but one has access to ob.x and the other one doesn't. Can someone explain to me why that is?
The difference is, in the 1st case the protected member is accessed through the derived class. In the 2nd case the protected member is accessed through the base class, which is not allowed.
For protected members,
(emphasis mine)
A protected member of a class is only accessible
2) to the members and friends (until C++17) of any derived class of that class, but only when the class of the object through which the protected member is accessed is that derived class or a derived class of that derived class:
struct Base {
protected:
int i;
private:
void g(Base& b, struct Derived& d);
};
struct Derived : Base {
void f(Base& b, Derived& d) { // member function of a derived class
++d.i; // OK: the type of d is Derived
++i; // OK: the type of the implied '*this' is Derived
// ++b.i; // error: can't access a protected member through
// Base (otherwise it would be possible to change
// other derived classes, like a hypothetical
// Derived2, base implementation)
}
};
#include <iostream>
using namespace std;
class B {
protected:
int x;
public:
B() {
x = 78;
}
};
class D1 : virtual public B {
public:
D1() {
x = 15;
}
};
class D2 : virtual public B {
public:
D2() {
x = 37;
}
};
class C : public D2, public D1 {
public:
int get_x() {
return x;
}
};
int main()
{
C ob;
cout << ob.get_x();
return 0;
}
when the C object is created, the value of x is 15 instead of 78. I was wondering if it's because the last constructor called(which changed the value of x) was the D1 constructor?
I was wondering if it's because the last constructor called(which changed the value of x) was the D1 constructor?
Yes, that is exactly what happened. A class's base constructors are called in the order the ancestors are listed. Since D1 is listed last, its constructor is called last. B's constructor is called first to initialize x to 78, then D2's constructor overwrites x with 37, then D1's constructor overwrites x with 15.
My question is very similar like other's, but a bit different. I have a sample code:
class B1 {
private :
int * ptr;
public:
B1() : a{ 1 } { ptr = new int{ 2 }; }
B1(const B1& other) : a{ other.a } { ptr = new int{ *other.ptr }; }
~B1() { delete ptr; }
int a;
virtual void smthing() = 0;
};
class D : B1 {
public:
D(int i) : B1{} {}
D(const D& a) : B1{ a } {}
void smthing() { return; };
};
int main() {
D d { 3 };
D dd { d };
return 0;
}
I am using vs2015, and this code is works, but gives me error: object of abstract class type "B1" is not allowed...
If I remove this line D(const D& a) : B1{ a } {}, the base class copy constructor is called and there's no problem, but if I need the derived class copy constructor how can I make this work without error?
Thanks for the answer!
Consider following diamond-like multiple inheritance:
class base;
class d1 : virtual public base;
class d2 : virtual public base
class d3 : public d1, public d2;
base is a move-only class (having a large move-only buffer). So are d1, d2 and d3. Move constructor of d1 and d2 call move constructor of the base.
Then what should do move constructor of d3? Calling both move-ctors of d1 and d2 results in crashs (since move constructor of base is called twice.
Here I have a minimum compilable instance of the problem:
#include <iostream>
struct moveonly {
moveonly(): data(nullptr) {}
moveonly(const moveonly &) = delete;
moveonly(moveonly &&other) {
this->data = other.data;
other.data = nullptr;
}
~moveonly() {
if(data)
delete[] data;
}
char *data;
};
class base {
public:
base() = default;
base(const base &) = delete;
base(base &&other) : d(std::move(other.d)) { }
virtual ~base() = default;
int a;
int b;
moveonly d;
};
class d1 : virtual public base {
public:
d1() = default;
d1(const base &) = delete;
d1(d1 &&other) : base(std::move(other)) { }
int x;
int y;
};
class d2 : virtual public base {
public:
d2() = default;
d2(const base &) = delete;
d2(d2 &&other) : base(std::move(other)) { }
int r;
int s;
};
class d3 : public d1, public d2 {
public:
d3() = default;
d3(const base &) = delete;
// What should I do here?
d3(d3 &&other) : d1(std::move(other)), d2(std::move(other)) { }
int p;
int q;
};
int main()
{
d3 child;
child.d.data = new char[1024];
for(size_t i = 0; i < 1024; ++i)
child.d.data[i] = i * 2;
d3 other_child = std::move(child);
for(size_t i = 0; i < 1024; ++i) {
std::cerr << other_child.d.data[i] << ' ';
}
std::cerr << std::endl;
return 0;
}
As with all virtual inheritance, the virtual bases are initialized by the most-derived object, so:
d3(d3 &&other)
: base(std::move(other)), // <== *you* initialize the base
d1(std::move(other)),
d2(std::move(other)) {}
What's wrong with asking the compiler to provide the implementation?
d3(d3 &&) = default; // I think this the best approach as it is less error pron .
You could write it out if you really wanted to:
d3(d3 &&other): base(std::move(other)), d1(std::move(other)), d2(std::move(other))
{
}