c++ Derived class object has no member, why? - c++

I have this problem in my homework.
I have this 2 classes:
-an user class:
class user
{
protected:
int id;
std::string password;
std::string name;
bool online;
static int usersCounter;
static int onlineCounter;
public:
user(std::string = "user", std::string = "1234");
bool connect(std::string);
void disconnect();
void changePassword(std::string);
void changeName(std::string);
virtual void printInfo();
static int getOnlineNo()
{
return onlineCounter;
}
static int getTotalUsers()
{
return usersCounter;
}
friend class admin;
};
and an admin class:
class admin : public user
{
public:
admin(std::string name = "admin", std::string password = "admin"):
user(name, password){}
void disconnectUser(user&);
void viewUsers( user** );
void printInfo() override;
};
When I try to make a polymorphic object and call a function from admin (a function specific for admin, as disconnectUser(...) or viewUsers(...)) I get errors as "class "user" has no member "viewUsers".
user* usr = new admin();
usr->viewUsers(&usr);//error
Is this something usual and I did a wrong design or It should work and I am doing something wrong?

As pointed out in the comment if you define a class of type A you can access only public methods and property of that class.
In your case, viewUsers is present only in the admin class while you're using the generic user class.
You must use inheritance very careful because is very easy to put the wrong methods inside classes or make a wrong inheritance. For example, are you sure the method viewUsers must be inside the admin class? Usually, if a function doesn't depend on the class is best put it outside the class.

Related

Is there a way in C++ to restrict a function of a given class to another class only(without using inheritance, friend)?

I want to design a class having a function which should be restricted to be called from another class only. Specifically, in the given code
class Club
{
int id;
string name;
vector<string> members;
int generateId()
{
static int i=1;
return i++;
}
public:
Club(string name) { this->name = name; this->id = generateId(); }
void registerMember(string memberName) { members.push_back(memberName); }
int getId() { return id; }
};
class Application
{
vector<Club> clubs;
public:
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
}
};
An user(public user) can create an object of the class Club and register using the function registerMember() since it's public. I want the user to register via an object of the class Application, using the addMemberToClub() function only. If the user goes by the former way mentioned, I can't keep track of the user. Is there a way to enforce the latter?
I don't want to use the access modifier protected since inheritance has no meaning here.
I don't want to use the friend keyword, since it's considered bad practice.
Here is a "lock-and-key" way to permit another class (and only that class) or even a single function in another class to access just one member function, unlike friend which exposes all private members at the same time:
#include <iostream>
class Key;
class Locked
{
static const char* const Greeting;
public:
static Key secretive();
static void attacker();
};
struct Admin
{
void doit();
};
class Key
{
~Key() = default;
//friend class Admin;
friend void Admin::doit();
friend Key Locked::secretive();
};
void Admin::doit()
{
Locked::secretive();
std::cout << Locked::Greeting; // compile error
}
constexpr const char* Locked::Greeting = "Hello!\n";
Key Locked::secretive()
{
std::cout << Greeting;
return Key();
}
void Locked::attacker()
{
std::cout << Locked::Greeting; // ok, it's just private
Locked::secretive(); // compile error, it's locked down tight
}
int main()
{
Admin a;
a.doit();
std::cout << Locked::Greeting; // compile error
Locked::secretive(); // compile error
}
It also works around the "which class is declared first?" problem that prevents two classes from mutually friending individual member functions of each other, because the restricted operation needs to follow only a forward declaration of the key type; the full definition of the other type can (and in this example does) appear above the key definition, allowing individual members to be named in the key type's friend directive.
Note that in this solution the "obvious" fact that other members of the same class can access the locked function is NOT true. The compiler prevents Locked::attacker() from calling Locked::secretive().
Note also that I've used static in this example to minimize the number of objects I had to create, but the approach works just fine for non-static member functions too.
A potentially MUCH easier way to restrict what part of the program can call your protected function is with a simple flag:
class Application
{
static bool addingMember = 0;
public:
static bool isRegistrationOk() { return addingMember; }
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
addingMember = true;
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
addingMember = false;
}
};
void Club::registerMember(string memberName)
{
assert(Application::isRegistrationOk());
members.push_back(memberName);
}
Much easier to grok, but it's a runtime check not compile-time, and requires additional work to be made thread-safe. But it accomplishes the goal with no usage of friend or inheritance.
friend is an appropriate mechanism to use in this case. Make registerMember private in Club, and Club can grant friendship to Application:
class Club
{
// ...
void registerMember(string memberName) { members.push_back(memberName); }
public:
// ...
friend class Application;
};
Now only Application can call registerMember, and Club as well, of course.
Here's a demo.

Shared method between two classes

I'm trying to share a method between two classes, where each one is using its private attribute, like this :
class DbWriter {
public:
int GetIdFromDB(QString codVEI) //<! uses mDbWriteQuery
private:
QSqlQuery mDbWriteQuery;
}
class DbReader {
public:
int GetIdFromDB(QString codVEI) //<! uses mDbReadQuery
private:
QSqlQuery mDbReadQuery;
}
I want to make something like a friend method, but with each one knowing their own attribute member, and without having to create a class and inherit from it these two classes because it doesn't work in my case.
If you want to share an implementation just use a common free function:
namespace detail {
int GetIdFromDB(QString codVEI, QSqlQuery const& query);
}
Include/link it with both classes and have them call it.
Passing the query as a parameter avoids senseless coupling by not introducing friendship into the mix.
I would do it using polymorphic classes. E.g.
class DbObject
{
public:
virtual int GetIdFromDB(const QString &codVEI) = 0;
private:
QSqlQuery mQuery;
};
class DbWriter : public DbObject
{
public:
int GetIdFromDB(const QString &codVEI) override;
};
class DbReader : public DbObject
{
public:
int GetIdFromDB(const QString &codVEI) override;
};
Usage:
auto dbObject = std::make_shared<DbWriter>();
int id = dbObject->GetIdFromDB("foo"); // Calls write query
dbObject = std::make_shared<DbReader>();
id = dbObject->GetIdFromDB("foo"); // Calls read query
Update
Fixed the DbReader class declaration - it should also derive from DbObject class.

c++ expected unqualified-id (class inheritance)

I have an application that has subclasses of User.
At the moment, I'm trying to pass an int which will be used to identify the user login number, however, I'm having problems declaring my subclass constructor.
User.h
class User
{
public:
User(int);
private:
int loginNumber;
};
User.cpp
User::User(int theLoginNUmber)
:LoginNumber(theLoginNumber) { }
AdminUser.h
class AdminUser : public User
public:
AdminUser(int);
private:
int loginNumber;
};
AdminUser.cpp
AdminUser::User(int theLoginNumber) // requires unqualified-id
:loginNumber(theLoginNumber) {}
You got definition of Admin user constructor wrong, here is the correct one:
AdminUser::AdminUser(int theLoginNumber)
: User(theLoginNumber) { }
Since User doesn't have default constructor, you have to call the parametric one from initialization section.
However loginNumber can be protected in User class:
class User {
public:
User(int);
protected:
int loginNumber;
};
Now you inherit loginNumber as protected so you don't need it in AdminUser:
class AdminUser : public User
public:
AdminUser(int);
};
Note: it contains loginNumber with correct value(set by constructor).
As #Mossi92 noted, you can go a bit further and implement a getter into User class, which will be inherited too:
class User {
public:
User(int);
protected:
int loginNumber;
int login() const noexcept {
return loginNumber;
}
};
However in this case you should think which class access modifier is the best this function. I'd say login number should be something invisible to outer world so I chose protected. This function now can be called only from inherited or friend classes.
Lets add simple print which calls inherited function in constructor:
AdminUser::AdminUser(int theLoginNumber)
: User(theLoginNumber) {
std::cout << login() << "\n";
}
And if we run:
int main() {
AdminUser admin(1234);
return 0;
}
output:
1234

Implement possibility to access class member static as well as non-static on a derived class

I have the following classes.
// My baseclass
class Item {
public:
virtual const std::string GetItemName() = 0;
};
// My derived class
class Shovel : public Item {
private:
static const std::string _ITEM_NAME = "tool_shovel";
public:
const std::string GetItemName(){
return _ITEM_NAME;
}
}
With this i can access the names of my Item objects like this:
Item* myItem = new Shovel();
myItem.GetItemName(); // Returns "tool_shovel" ofcourse
I would now also like to access the name of an item without having an instance of it like this.
Shovel::GetItemName();
I know it is not possible to implement a virtual static function.
but is there any way to implement this in a 'nice' way or is this more a problem in my concept?
Thanks for the help!
I didn't know it is possible to call a static function directly from an instance, so i solved my problem now with 2 methods.
One public static function, so i can get the name of an item at any time. And another private non-static function to let the baseclass get the name of the current item.
Here is the code:
// My baseclass
class Item {
protected:
virtual const std::string _GetItemName() = 0;
};
// My derived class
class Shovel : public Item {
private:
static const std::string _ITEM_NAME = "tool_shovel";
protected:
const std::string _GetItemName(){
return _ITEM_NAME;
}
public:
static const std::string GetItemName(){
return _ITEM_NAME;
}
};
I hope this helps anyone. If you have questions feel free to ask.

Export a class with std::string

I know this subject has been covered and re-talked, but I still get stuck every time I need to do something like that, and the internet is full of different answers.
so I decided to simply ask how to deal with such situation once and for all.
Lets say I have the following class:
class PETS_EXPORT_API dog
{
public:
dog(std::string name):_name(name){}
~dog(){}
private:
std::string _name;
};
Obviously this code would generate a warning because I'm trying to export std::string. How do I solve such issue ?
thanks!
Alternative to Joe McGrath's answer:
If you really want your clients to have access to Dog public & protected interface, and does not make sense to have an abstract interface,
You could use the pImpl idiom, to hide the private interface.
Additionally you could export the string in the form of chars
Hide your original dog:
class Dog_Impl // your original class
{
public:
Dog_Impl(std::string name):_name(name){}
~Dog_Impl(){}
string::get_name();
private:
std::string _name;
};
Put this into your API:
class Dog_Impl; // fwd declaration
class PETS_EXPORT_API Dog {
public:
Dog(const char *name);
~Dog();
const char *get_name();
private:
Dog_Impl *pImpl;
};
The implementation should simply pass all public & protected interface to the pImpl:
Dog::Dog(const char *name)
{
pImpl = new Dog_Impl(name);
}
Dog::~Dog()
{
delete pImpl;
}
const char *Dog::get_name()
{
return pImpl->get_name().c_str();
}
You don't want to export the private members. Only the public interface. Make an abstract base class and export it.
struct DogInterface
{
virtual string IAmADog(void) = 0; // your public interface goes here
};
// Factory function that creates dogs
extern "C" PETS_EXPORT_API DogInterface* APIENTRY GetDog();
If you just want to export the string for access
__declspec(dllexport) const char* MyExportedString()
{
return myString.c_str()
}