Cast to reference to base class with no additional data members? - c++

Is it safe to static_cast a concrete base class object, to a reference to a derived concrete class object when the derived class has no additional data members? Here is a simple example for illustration:
#include <array>
struct Foo : std::array<int,3>
{
Foo() : std::array<int,3>{1,2,3} {}
void hello() { std::cout << "Hello\n"; }
};
Foo test()
{
std::array<int,3> a{4,5,6};
return static_cast<Foo&>(a);
}

As others have noted, this is undefined behavior (so unsafe) even though it is likely to work for POD types with no virtual members or bases. It's easy enough to do it safely by just defining the appropriate constructor:
#include <array>
struct Foo : std::array<int,3>
{
Foo() : std::array<int,3>({1,2,3}) {}
void hello() { std::cout << "Hello\n"; }
Foo(const std::array<int, 3> &a) : std::array<int,3>(a) {}
};
Foo test()
{
std::array<int,3> a{4,5,6};
return a;
}
and then no cast is actually needed.
If for some bizarre social reason (assignment requirements?) you're not allowed to change the definition of Foo, you can get around this by using an adaptor class:
struct Foo : std::array<int,3>
{
Foo() : std::array<int,3>({1,2,3}) {}
void hello() { std::cout << "Hello\n"; }
};
struct FooAdaptor : public Foo {
FooAdaptor(const std::array<int, 3> &a) {
*this = a;
}
};
Foo test()
{
std::array<int,3> a{4,5,6};
return FooAdaptor(a);
}
but I would not recommend this for real code

Related

Namehiding and overriding - Is there a way to make a function explicitly not overriding

I would like to hide a virtual method instead of override. I know for historic / compatibility reasons the override specifier is optional and overriding happens implicitly.
To stop overriding I usually adjusted the signature by adding a defaulted "Dummy" parameter. Is there a better way?
Assume this code:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
class B : public A
{
public:
void Foo() /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo - but prints B::Foo
}
What I did so far is this:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
template<typename T>
class reintroduce{};
class B : public A
{
public:
void Foo(reintroduce<B> = {}) /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo
}
The question is not too clear on the requirements of "hiding" but the following effectively "hides" the inherited method in the derived class, while not changing its visibility/accessibility in the base class.
#include <iostream>
class A {
public:
virtual void Foo()
{ std::cout << "A::Foo"; }
};
class B : public A
{
private:
using A::Foo;
};
int main()
{
B b;
b.Foo(); // error, cannot access private member
b.A::Foo(); // ok, calls A::Foo
A& a = b;
a.Foo(); // ok, calls A::Foo
}

Method nonvisibility in base class despite definition in derived class; polymorphism and using `virtual` keyword

#include <iostream>
class A {
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() { return foo; }
};
class C {
private:
A baz;
public:
C(A faz) { baz = faz; }
A get() { return baz; }
};
int main(void) {
C boo(B(1));
std::cout << boo.get().method() << std::endl;
return 0;
}
I have a base class A which B is a derived class of. Class C takes an A yet I have passed a derived class (B) in its place. No warnings or errors passing a B to C, but I'd like to have method visibility of method() in the above situation.
I'm not very familiar with virtual but I did try to add virtual int method() = 0; to A which lead to further errors.
Consider were I to add a second derived class:
class D : public A {
public:
D(int bar) { foo = bar; }
int method() { return foo+1; }
};
I'd like C to be able to take either B or D and my best assumption would be to take an A and let it handle it.
How do I use polymorphism correctly in this fashion?
Expected output with the below:
int main(void) {
C boo(B(1));
C boz(D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Would be:
1
3
First of all, in order to use A polymorphically, you need to add a virtual destructor, otherwise you will run into undefined behavior when trying to destroy the object. Then the method that you want to call through A must be virtual as well. If it shouldn't have an implementation in the base class itself, make it pure virtual:
class A {
protected:
int foo;
public:
virtual ~A() {}
virtual int method() = 0;
};
Then in C you need to use pointers or references to A, since polymorphism only works with those.
If you want C to own the A, as your code example to suggest, then you need to provide a destructor deleting the pointer and you need to disable copying of the class (or decide on some useful semantics for it):
class C {
private:
C(const C&); // Don't allow copying
C& operator=(const C&); // Don't allow copying
A* baz;
public:
C(A* faz) : baz(faz) { }
~C() { delete baz; }
A& get() { return *baz; }
};
int main(void) {
C boo(new B(1));
C boz(new D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Ideally you would upgrade to C++11 and use std::unique_ptr<A> instead of A* as member. But even if you can't do that, consider using boost::scoped_ptr<A>, which will manage the deletion for you (you don't need the destructor) and will make the class non-copyable by default. It also provides better exception-safety to encapsulate allocations in smart pointers like that.
If you need to call method() of type B using base class type A there has to be lookup during the runtime. The lookup is necessary to answer the question: Which method should be called? - the one that corresponds the type in a current line? Or other method in inheritance hierarchy?" If you expect method() from class B to be called when you have pointer or reference to A then you have to create a lookup table. This table is called vtable (from virtual functions table) and it's defined by adding virtual keyword to functions.
#include <iostream>
class A {
public:
virtual ~A(){}
virtual int method() = 0;
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() {
std::cout << "Calling method() from B" << std::endl;
return foo; }
};
class C {
private:
A* baz;
public:
C(A* faz) { baz = faz; }
A* get() { return baz; }
};
int main(void) {
A* element = new B(1);
C boo(element);
boo.get()->method();
return 0;
}
It prints "Calling method() from B". Please keep in mind that the code is for presentation purposes and it's not good from best practices perspective.

polymorphism with reference member variable

Can someone tell me what is wrong with my program below? I am using a reference member variable in a class for polymorphism. I am expecting the second cout to say "derived2" but it says "base";
#include <iostream>
// Example program
#include <iostream>
#include <string>
class base
{
public:
virtual void print(){ std::cout<<"base"<<std::endl;}
};
class derived: public base
{
public:
virtual void print(){ std::cout<<"derived"<<std::endl;}
};
class derived2: public base
{
virtual void print(){ std::cout<<"derived2"<<std::endl;}
};
class foo
{
public:
base & bar;
base boo;
derived foobar;
derived2 foobar2;
foo(): bar(boo){}
void newfoo(base & newfoo){ bar = newfoo; bar.print();}
};
int main()
{
foo test;
test.bar.print();
test.newfoo(test.foobar2);
}
Output:
base
base
As mentioned by others, you cannot reassign a reference.
Whenever you do something like bar = newfoo you are not resetting the reference. Instead you are invoking operator= for bar with newfoo as an argument.
Therefore, in your case you are slicing your objects and (let me say) copying its base part in bar.
A kind of reference-like tool to which you can reassign exists in the standard template library and it's called std::reference_wrapper.
It follows an example based on your code that uses it and has the expected behavior:
#include<functional>
#include <iostream>
#include <string>
class base
{
public:
virtual void print() { std::cout<<"base"<<std::endl;}
};
class derived: public base
{
public:
virtual void print(){ std::cout<<"derived"<<std::endl;}
};
class derived2: public base
{
virtual void print(){ std::cout<<"derived2"<<std::endl;}
};
class foo
{
public:
std::reference_wrapper<base> bar;
base boo;
derived foobar;
derived2 foobar2;
foo(): bar(boo){}
void newfoo(base & newfoo){ bar = newfoo; bar.get().print();}
};
int main()
{
foo test;
test.bar.get().print();
test.newfoo(test.foobar2);
}
In this case, operator= actually rebinds the reference to the given object. Anyway, as you can see, in this case you must invoke get to access the underlying reference.
Note: set aside the example above, your code isn't the typical use case for a std::reference_wrapper.
I mentioned it only for the sake of completeness.
You can't 'reassign' the reference. When assignment operator is used with the reference, it assigns the underlying value.
Thus, bar = newfoo; simply assigns foo of the base type to foobar, slicing it in the process.
You could have a different behavior if you'd substitute references with pointers, which can be re-assigned.
bar is a reference to boo, and boo is of type base whatever you assign to it.
Assignment can only change a variables value, not its type.
Polymorphism does not work with references. Try this:
#include <iostream>
// Example program
#include <iostream>
#include <string>
class base
{
public:
virtual void print(){ std::cout << "base" << std::endl; }
};
class derived : public base
{
public:
virtual void print(){ std::cout << "derived" << std::endl; }
};
class derived2 : public base
{
virtual void print(){ std::cout << "derived2" << std::endl; }
};
class foo
{
public:
base* bar;
foo(): bar(0) {}
void newfoo(base* newfoo){ bar = newfoo; bar->print(); }
};
int main() {
foo test;
test.newfoo(new derived2);
}

Call virtual function after derived class object construction

Here is some sample code:
#include <iostream>
class A {
public:
virtual void foo() {
std::cout << "base" << std::endl;
}
A() {
foo();
}
};
class B : public A {
int a;
public:
void foo() {
std::cout << "derived" << std::endl;
}
B(int a) :
a(a) {}
};
int main() {
B o(1);
return 0;
}
I want foo() to get called every time some A derived object is constructed. I do not want to call foo() explicitly in every derived class constructor.
Is there a way to do this in some elegant way?
There is no way you can call an overridden foo() from a base class constructor, no matter what you do. When the base class constructor is called, the derived class object has not been constructed yet, so you cannot call any of its methods or access any of its members. This is true for virtual functions and regular functions as well. In a base class constructor, the this pointer is pointing at the base class, not the derived class.
A potential workaround is to delegate construction to a separate function that clients will have to call instead. Then have that function call foo after construction:
class A {
public:
virtual void foo() {
std::cout << "base" << std::endl;
}
template<typename T, typename ... Args>
static T construct(Args ... args)
{
T newT{ args... };
newT.foo();
return std::move(newT);
}
protected:
A() {
//Construct A
}
};
class B : public A {
int a;
public:
void foo() {
std::cout << "derived" << std::endl;
}
B(int a) :
a(a) {}
};
int main()
{
B o = A::construct<B>(1);
A a = A::construct<A>();
return 0;
}

Virtual inheritance and static inheritance - mixing in C++

If you have something like this:
#include <iostream>
template<typename T> class A
{
public:
void func()
{
T::func();
}
};
class B : public A<B>
{
public:
virtual void func()
{
std::cout << "into func";
}
};
class C : public B
{
};
int main()
{
C c;
c.func();
return 0;
}
Is func() dynamically dispatched?
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
Edit: My code didn't compile? Sorry guys. I'm kinda ill right now. My new code also doesn't compile, but that's part of the question. Also, this question is for me, not the faq.
#include <iostream>
template<typename T> class A
{
public:
void func()
{
T::func();
}
};
class B : public A<B>
{
public:
virtual void func()
{
std::cout << "in B::func()\n";
}
};
class C : public B
{
public:
virtual void func() {
std::cout << "in C::func()\n";
}
};
class D : public A<D> {
void func() {
std::cout << "in D::func()\n";
}
};
class E : public D {
void func() {
std::cout << "in E::func()\n";
}
};
int main()
{
C c;
c.func();
A<B>& ref = c;
ref.func(); // Invokes dynamic lookup, as B declared itself virtual
A<D>* ptr = new E;
ptr->func(); // Calls D::func statically as D did not declare itself virtual
std::cin.get();
return 0;
}
visual studio 2010\projects\temp\temp\main.cpp(8): error C2352: 'B::func' : illegal call of non-static member function
visual studio 2010\projects\temp\temp\main.cpp(15) : see declaration of 'B::func'
visual studio 2010\projects\temp\temp\main.cpp(7) : while compiling class template member function 'void A<T>::func(void)'
with
[
T=B
]
visual studio 2010\projects\temp\temp\main.cpp(13) : see reference to class template instantiation 'A<T>' being compiled
with
[
T=B
]
I'm not sure I understand what you're asking, but it appears you are missing the essential CRTP cast:
template<class T>
struct A {
void func() {
T& self = *static_cast<T*>(this); // CRTP cast
self.func();
}
};
struct V : A<V> { // B for the case of virtual func
virtual void func() {
std::cout << "V::func\n";
}
};
struct NV : A<NV> { // B for the case of non-virtual func
void func() {
std::cout << "NV::func\n";
}
};
If T does not declare its own func, this will be infinite recursion as self.func will find A<T>::func. This is true even if a derived class of T (e.g. DV below) declares its own func but T does not.
Test with different final overrider to show dispatch works as advertised:
struct DV : V {
virtual void func() {
std::cout << "DV::func\n";
}
};
struct DNV : NV {
void func() {
std::cout << "DNV::func\n";
}
};
template<class B>
void call(A<B>& a) {
a.func(); // always calls A<T>::func
}
int main() {
DV dv;
call(dv); // uses virtual dispatch, finds DV::func
DNV dnv;
call(dnv); // no virtual dispatch, finds NV::func
return 0;
}
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
Somewhat contradictory, isn't it? A user of class A may know nothing about B or C. If you have a reference to an A, the only way to know if func() needs dynamic dispatch is to consult the vtable. Since A::func() is not virtual there is no entry for it and thus nowhere to put the information. Once you make it virtual you're consulting the vtable and it's dynamic dispatch.
The only way to get direct function calls (or inlines) would be with non-virtual functions and no indirection through base class pointers.
Edit: I think the idiom for this in Scala would be class C: public B, public A<C> (repeating the trait with the child class) but this does not work in C++ because it makes the members of A<T> ambiguous in C.
In your particular example, there's no need for dynamic dispatch because the type of c is known at compile time. The call to B::func will be hard coded.
If you were calling func through a B*, then you would be calling a virtual function. But in your highly contrived example, that would get you to B::func once again.
It doesn't make much sense to talk about dynamic dispatch from an A* since A is a template class - you can't make a generic A, only one that is bound to a particular subclass.
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
As others have noticed, it's really hard to make sense of that question, but it made me remember something I have learned a long time ago, so here's a very long shot at answering your question:
template<typename Base> class A : private Base
{
public:
void func()
{
std::count << "A::func";
}
};
Given this, it depends on A's base whether func() is virtual. If Base declares it virtual then it will be virtual in A, too. Otherwise it won't. See this:
class V
{
public:
virtual void func() {}
};
class NV
{
};
class B : public A<V> // makes func() virtual
{
public:
void func()
{
std::count << "B::func";
}
};
class C : public A<NV> // makes func() non-virtual
{
public:
void func()
{
std::count << "C::func";
}
};
Would this happen to answer your question?
Whether the function is dynamically dispatched or not depends on two things:
a) whether the object expression is a reference or pointer type
b) whether the function (to which overload resolution resolves to) is virtual or not.
Coming to your code now:
C c;
c.func(); // object expression is not of pointer/reference type.
// So static binding
A <B> & ref = c;
ref.func(); // object expression is of reference type, but func is
// not virtual. So static binding
A<D>* ptr = new D;
ptr->func(); // object expression is of pointer type, but func is not
// virtual. So static binding
So in short, 'func' is not dynamically dispatched.
Note that :: suppresses virtual function call mechanism.
$10.3/12- "Explicit qualification with
the scope operator (5.1) suppresses
the virtual "call mechanism.
The code in OP2 gives error because the syntax X::Y can be used to invoke 'Y' in the scope of 'X' only if 'Y' is a static member in the scope of 'X'.
Seems you just had to add a little trace and usage to answer your own question...
#include <iostream>
template<typename T> struct A {
void func() {
T::func();
}
};
struct B1 : A<B1> {
virtual void func() {
std::cout << "virtual void B1::func();\n";
}
};
struct B2 : A<B2> {
void func() {
std::cout << "void B2::func();\n";
}
};
struct C1 : B1 { };
struct C2 : B2 { };
struct C1a : B1 {
virtual void func() {
std::cout << "virtual void C1a::func();\n";
}
};
struct C2a : B2 {
virtual void func() {
std::cout << "virtual void C2a::func();\n";
}
};
int main()
{
C1 c1;
c1.func();
C2 c2;
c2.func();
B1* p_B1 = new C1a;
p_B1->func();
B2* p_B2 = new C2a;
p_B2->func();
}
Output:
virtual void B1::func();
void B2::func();
virtual void C1a::func();
void B2::func();
Conclusion: A does take on the virtual-ness of B's func.