1

I have two class.

class A:

class B: public A
{
     //new function
     void setHint(...);
}

And have struct data.

typedef std::shared_ptr<A> window_ptr;
std::stack<window_ptr> m_windowsStack;
m_windowsStack.push(std::make_shared<A>("Hint"));
m_windowsStack.push(std::make_shared<B>("Game"));

And have function find in stack:

std::shared_ptr<A> WindowManager::findWindow(std::string title)
{
    ... return result;
}

And use function for find element in stack:

auto w = findWindow("Game"); //return element type B 
w->setHint(window);

But it turns out that function findWindow return type A. I get error "'class A' has no member named 'setHint' w->setHint(window);"

Do I need to declare setHint function in class A as virtual function? How do I make a variable to automatically understand that it is of type B?

3
  • 1
    Just cast the result, i.e. auto w = findWindow("Game"); -> auto w = static_cast<B*>(findWindow("Game")); Commented Jan 6, 2017 at 8:33
  • 1
    class A: is an error, please write real code. Also I am not sure if you intended setHint to be a variadic function Commented Jan 6, 2017 at 8:35
  • @M.M class A: {} it's abstract class, my class big and there is a lot of unnecessary variables for this question \ functions. :) Commented Jan 6, 2017 at 8:38

2 Answers 2

5

Without understanding your entire project, I'd say the right solution is likely to add a virtual function in the base class.

class A {
 public:
  virtual void setHint(/*...*/) { /* some default implementation */}
  // or pure virtual
  virtual void setHint(/*...*/) = 0;

  virtual ~A() = default; // base class should have a virtual destructor
};

class B: public A {
 public:
  void setHint(/*...*/) override;
};

Alternatively, If you know for sure that the type pointed to the return value from findWindow is a B you can simply static_pointer_cast it down

auto w = std::static_pointer_cast<B>(findWindow("Game"));
w->setHint(window);

If you aren't sure, and A is a polymorphic type (having any virtual functions) you can dynamic_pointer_cast and check for null

if (auto w = std::dynamic_pointer_cast<B>(findWindow("Game"))) {
  w->setHint(window);
}
Sign up to request clarification or add additional context in comments.

5 Comments

another option is dynamic_cast<B&>(*w).setHint(window); - this will throw an exception instead of undefined behaviour in case it is not the expected type
@M.M right, but not if OP is trying to not add virtual functions
He said in a comment to the question that A is an abstract class (implying it already contains virtual functions)
You might want to use cast operators for shared_ptr instead of casting the raw pointer stored.
@Holt indeed, that does eliminate the extra variable
2

Your choices are:

  1. Declare setHint virtual in class A

  2. Use dynamic_pointer_cast

Thus

auto w = std::dynamic_pointer_cast<B>(findWindow("Game"));
assert(w);  // Will be nullptr if cast fails.
w->setHint(window);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.