Domanda

I should specify that I'm a bit new to OOP. I'm tying to make a vector of type pointer to Person that has a method GetName() and access a method GetSpg() from my Player class that derives Person. I get an error "GetSpg() is not a member of Person". My question would be: is there any way to access both functions from the vector so that if it points to a Person to not show that method but if it is to do so?

Here is my code:

#ifndef _PERSON_H
#define _PERSON_H

#include <iostream>
#include <algorithm>

typedef std::pair<std::string, std::string> StrPair;

class Person :private StrPair
{

  public:
    Person(const std::string& fn = "none", const std::string& sn = "none")         :StrPair(fn,sn){};
    virtual void Update(const std::string& fn, const std::string& sn){ StrPair::first = fn; StrPair::second = sn; };
    virtual const StrPair& GetName(){ return (const StrPair&)(*this); };
};
#endif

typedef std::pair<int, int> IntPair;

class Jucator: public Person, private IntPair
{
    std::string tip;
    int spg;
    int average;

  public:
    Jucator(const std::string& fn = "none", const std::string& sn = "none", 
        const std::string& t = "", const int& _spg = 0, const int& _avr = 0, 
        const int& _g = 0, const int& _r = 0) :Person(fn, sn),tip(t),spg(_spg),average(_avr),IntPair(_g,_r){};
    virtual void Update(const std::string& fn, const std::string& sn, const std::string& t, const int& _spg, const int& _avr,
        const int& _g, const int& _r){
    Person::Update(fn, sn); tip = t; spg = _spg; average = _avr; IntPair::first = _g; IntPair::second = _r;
};

virtual const int& GetSpg(){ return spg; };
È stato utile?

Soluzione

You can't. A pointer of type Person can only be used to access data/addresses(functions) that are part of the Person object. The compiler simply has no way of knowing what all classes could be deriving from Person and hence which operations are legal.

Have a look at Dynamic casting. MSDN Reference | Tutorial

In brief:

Player* pPlayer = dynamic_cast<Player*>(pPerson);
if (pPlayer) {
  //Use the pointer like a player pointer
  //Note: You can only call player functions from pPlayer, not pPerson
} else {
  //Use the pointer like a person pointer
}

Note that this casting is a runtime operation. At compile time, the compiler sees you using the Player pointer to access Player code, which it is happy to allow!

Disclaimer: I found your code tough to follow, so consider this an answer to your question in text

Altri suggerimenti

The problem you're facing is very similar to the classic animal/cat/dog example. The basic idea is you have a base class - Animal - and two classes that derive from it - Cat and Dog.

class Animal {
    public:
    Animal() {}
    virtual ~Animal() {}
};

class Dog : public Animal {
    public:
    Dog() : Animal() {}

    void bark() { std::cout << "Woof" << std::endl; }

    ~Dog() {}
}

class Cat : public Animal() {
    public:
    Cat() : Animal() {}

    void meow() { std::cout << "Meow" << std::endl; }

    ~Cat() {}
}

Now, if you declare a Cat or a Dog object, it's pretty obvious that you can call either bark() or meow(); but if you declare an Animal object, there's no way of knowing whether it's a Cat or a Dog, so you can't call either method.

In your case, you have Person as the base class and Player as the derived. You may further derive Person and have a new class, NonPlayer, so that Person would play the same role as Animal, and Player and NonPlayer would be Cat and Dog respectively.

If you really need to access Player methods from pointers to Person objects, you need to cast the Person* to Player* before. However, you need to be sure before that the pointer inside is a Player*. If it isn't, you'll most likely get a compilation error.

There are concepts of upcasting and downcasting which are essential to understand your problem. You can use the concept of dynimc_cast, this Link would be helpful to understand.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top