1

Say I've got the following code:

class A {};

class B : public A {
public:
    explicit B(string s) {}

    friend ostream &operator<<(ostream &out, const B &b) {
        out << "b";
        return out;
    }
};

class C : public A {
public:
    explicit C(int i) {}

    friend ostream &operator<<(ostream &out, const C &c) {
        out << "c";
        return out;
    }
};

Then, I have a function like this:

A s(int i) {
    if (i == 0)
        return dynamic_cast<B>(B("hello world")); // first try
    else {
        return C(12); // second try
    }
}

In main, I write the followings:

#include <iostream>
using namespace std;
int main() {
    cout << *(s(0)) << endl; // should print "b"
    cout << *(s(1)) << endl; // should print "c"
    return 0;
}

How can I do it? (any answer should work for C++14)

Thanks in advanced.

Niles
  • 75
  • 1
  • 6
  • 2
    Dynamic casts require RTTI being available, which is only the case for virtual classes. Add a virtual destructor to `A` and you should be able to cast as you want. – Aconcagua Jun 14 '23 at 12:43
  • 5
    `s` return an (sliced) `A`, returning `std::unique_ptr` would avoid the slicing. – Jarod42 Jun 14 '23 at 12:46
  • 1
    https://stackoverflow.com/questions/15188894/why-doesnt-polymorphism-work-without-pointers-references – Cory Kramer Jun 14 '23 at 12:46
  • 2
    Doing a `dynamic_cast` from `B` to `B` is pointless. That's probably an attempt to work around [object-slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing)? – Lukas-T Jun 14 '23 at 12:47
  • 1
    @Aconcagua there's another snag, `dynamic_cast` only works on pointers and references. I don't see either in this code. – Mark Ransom Jun 14 '23 at 12:48
  • almost. I can use smart pointers (that's not a problem), BUT anyway I want it to work like in Java, where I can do ```A a = new B()``` and it will work like B. Is it even possible in C++? – Niles Jun 14 '23 at 12:49
  • @MarkRansom Indeed – have been going to add/extend comments but others have been faster than me ;) – Aconcagua Jun 14 '23 at 12:49
  • @Niles It *is* possible, but you *need* pointers or references for! Java does so as well, solely that it hides all this away from you... Remember that there are (implicit) reference types??? – Aconcagua Jun 14 '23 at 12:50
  • Side note: About [`using namespace std`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)… – Aconcagua Jun 14 '23 at 12:53
  • @Aconcagua I never use it. I wrote it here just to make things easier while asking ;) – Niles Jun 14 '23 at 12:55
  • 1
    You might do something like [that](https://godbolt.org/z/8vjqPzWhc). – Jarod42 Jun 14 '23 at 12:56
  • Typically you'll do such things with `std::unique_ptr`s – these are much cheaper in construction (you don't want to pay for what you don't need) – unless you know for sure in advance that the object *will* be shared. Your function might look like `std::unique_ptr s(int) { /*...*/ return std::make_unique(""); /*...*/ }`. – Aconcagua Jun 14 '23 at 12:56
  • 2
    The whole idea of inheritance is that a derived class models an "is a" concept. So usually when you need std::dynamic_cast it is a sign you need to either reconsider your design or check your code. It is much more common to access functionality through (abstract) baseclasses and overloaded virtual functions. – Pepijn Kramer Jun 14 '23 at 12:57
  • Can you explain to us what you are trying to do and why you think you need dynamic_cast? – Pepijn Kramer Jun 14 '23 at 13:01
  • By the way, even if you *do* fix all the issues around object slicing and so on you still won't get the desired output. You have defined global `operator<<`s for your types – but these are not considered if you have a pointer or reference to `A`! You need instead an operator accepting a `A` instance and call some *virtual* function on that one! Could look like: `class A { friend ostream& operator<<(ostream& s, A const& a) { a.printTo(s); return s; } virtual void printTo(ostream& s) = 0; };` – Aconcagua Jun 14 '23 at 13:07
  • 1
    I think you would benefit from a [good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282). Trying to learn C++ by guessing is futile, and knowing some things about Java doesn't help. – molbdnilo Jun 14 '23 at 13:08
  • @Niles *BUT anyway I want it to work like in Java* -- Do not use Java or any other programming language as a model in writing or learning C++. All that will happen if you continure to go down that path are C++ programs that 1) Have bugs, 2) Inefficient, or 3) Will look weird to a C++ programmer. Learn C++ as if Java doesn't exist. – PaulMcKenzie Jun 14 '23 at 13:50
  • No you don't want to work like java : Read this about [scopes](https://en.cppreference.com/w/cpp/language/scope) and hopefully you will start to understand how different C++ is from Java – Pepijn Kramer Jun 14 '23 at 14:01
  • @PepijnKramer -- *So usually when you need std::dynamic_cast it is a sign you need to either reconsider your design* -- I think this is a case of what I mentioned in my last comment, and that is using Java techniques in a C++ program. In Java, I have seen so much usage of `instanceof`, which is for all intent and purposes what `dynamic_cast` does. The problem is that Java programmers are taught to use this first, instead of thinking about their design. – PaulMcKenzie Jun 14 '23 at 14:02
  • 1
    @PaulMcKenzie I've seen the same with .Net. People use reflection if it is available.. Maybe Hyrum's law for languages ;) – Pepijn Kramer Jun 14 '23 at 14:05
  • Yes, it seems that programmers fall back to what's comfortable to them. The problem is that what is comfortable in Java is not so in C++. – PaulMcKenzie Jun 14 '23 at 14:16

0 Answers0