0

I'm trying to get my base class currency. To access and return the string from it's derived class pound. My instructor specifically said it's a non public type (so I'm assuming a protected member would be the best here) and to NOT declare it in the base class. I'm having trouble making a function string getCurtype()to return the string and friending the derived class pound in my base class isn't not dong what I'm expecting it to do.

I'm guessing friending my derived class to the base class, doesn't give it access to it's protected members as it's only accisble in the derived class pound? Can someone please suggest me a way to set a getter string getCurType()for my string currencyType = "dollar" as a protected member in my derived class pound?

class currency{ friend class pound; string getCurType(){return currencyType;}; void print(){ cout << "You have " << getPound() << " " << getCurType() << endl; } class pound : public currency{ protected: string currencyType = "pound"; } 

Error:

test.cpp:11:34: error: 'currencyType' was not declared in this scope string getString(){return currencyType;}; ^~~~~~~~~~~~ test.cpp:11:34: note: suggested alternative: 'currency' string getString(){return currencyType;}; ^~~~~~~~~~~~ currency 
3
  • 2
    That is a wrong design. Rethink and refactor it. And the answer is "no" Commented Jul 20, 2022 at 8:59
  • Aside: getDollar() is a pretty bad name for the amount of a currency, maybe you should change that to getAmount()? Commented Jul 20, 2022 at 9:41
  • please do not change the question after you got answers. Please do not incorporate answers into the question. As it stands now the answers make no sense, because they refer to code that is not present in the qeustion anymore. I will rollback your edit Commented Jul 20, 2022 at 9:44

3 Answers 3

3

Your design is backwards. Base classes should not need to know about derived classes other than the interface defined in the base. Define the interface you want to use in the base:

class currency{ public: virtual string getCurType() = 0; void print(){ cout << "You have " << getCurType() << endl; } }; class pound : public currency{ string currencyType = "pound"; public: string getCurType() { return currencyType; } }; 
Sign up to request clarification or add additional context in comments.

6 Comments

and possibly virtual int getAmount() = 0
@Caleth its also missing in OPs code, so I just removed it.
@Caleth and it doesnt necessarily need to be virtual. depends...
I've included more of my code in my main post. I'm getting a different error now
@pancakex62 I dont know what errors you have in main when I don't see the code. Note that your question should have contained a minimal reproducible example from the start. Then I could have fixed also other errors. But please do not change the question now, as there are already answers. You can open another question or show me the code, eg here: godbolt.org
|
2

You have misunderstanding here. To use currencyType in your base class it needs to be defined in that class. So in your case I would make the methods abstract in the abse class and implement it in the derived classes:

#include <iostream> #include <string> // this is your abstract base class (interface) class currency { public: virtual std::string getCurType() const = 0; virtual void print() const = 0; }; // implementation of pound class pound : public currency { public: virtual std::string getCurType() const override { return "pound"; } virtual void print() const override { std::cout << "You have " << getPound() << " " << getCurType() << std::endl; } private: int getPound() const { return 3; } }; 

Comments

0

I don't know if this is what your instructure is aiming for, but there is another way in C++ to access derived class's functions in a base class. It is called CRTP (curiously recurring template pattern)

In this approach, you access things in the base class, that are not defined in it, but only in derived classes. To enable this, you use a templated base class, that is instantiated with the derived class.

Your problem could be solved like this:

template<class T> class currency { public: string getCurType() { // Convert this to a derived type, and call what you need return static_cast<T*>(this)->currencyType; } }; // CRTP: Curiously, the template recurs... class pound : public currency<pound> { public: string currencyType = "pound"; }; 

However, this requires the called derived thing to be public. To make it protected (or even private), you must friend the Base class:

class pound : public currency<pound> { private: string currencyType = "pound"; friend class currency<pound>; }; 

But there is another more sophisticated approach, that does not require public or friended members, only protected. Via an intermediate accessor (see this article, found via this answer):

template<class T> class currency { public: string getCurType() { return accessor::get_currencyType(derived()); } private: // Helper for cleaner code T &derived() { return *static_cast<T*>(this); } struct accessor : public T { // This accessor is derived from the derived class! static string get_currencyType(T &t) { // C++ Standard prohibits direct access to protected members here. // But it allows indirect access via pointer to member auto access = &accessor::currencyType; return t.*access; } }; }; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.