抽象类和失去信息

时间:2016-03-07 22:15:24

标签: c++ abstract

我有一个关于从抽象类创建类以及如何剪切数据的问题。

假设我们有一个名为 Animal 的抽象类,以及实现所述类的名为 Cat Dog 的类。这两个类都实现了一个名为 update() Animal 方法;但是,在他们的更新方法中,他们访问私有方法和/或变量,这些方法和/或变量是自己独有的,而不是Animal类。我明白,如果我们以这种方式宣布课程......

Animal* dog = new Dog();
Animal* cat = new Cat();

我们只能访问只有Animal类特有的方法或变量;但是,如果我在每个类上调用 update()方法,并且此更新方法调用Cat和Dog中的独占成员,该怎么办?这是合法的,还是会因为我将它们创建为动物而被截断?

2 个答案:

答案 0 :(得分:3)

该语言不会强制您仅使用对方法' update()'的多态访问。

示例:

class Animal {
public:
   virtual void update() { std::cout << "Animal::update() " << std::endl; }
   virtual ~Animal(){}
};

class Cat : public Animal {
public:
   virtual ~Cat(){}
   virtual void update() { std::cout << "Cat::update() " << std::endl; }
};

class Dog : public Animal {
public:
   virtual ~Dog(){}
   virtual void update() { std::cout << "Dog::update() " << std::endl; }
};

int t395(void)
{
   Animal* dog = new Dog();
   Animal* cat = new Cat();

   dog->update();
   cat->update();

   dog->Animal::update();
   return (0);

}

// OUTPUT:
// Dog::update() 
// Cat::update() 
// Animal::update() 
  

...我们只能访问只有Animal的方法或变量   班级具体;

我同意......狗是动物,并且没有方法Bark,因此无法调用dog-&gt; bark()。但是,你可以添加一个方法&#34; virtual void talk()&#34;对所有这三个,也许虚拟空的Dog :: talk()只会调用它的本地Dog :: bark()方法,而Cat :: talk()只会调用它的本地Cat :: meow()方法

  

然而,如果我在每个类上调用update()方法,   并且此更新方法调用独占   猫与狗的成员。这是合法的,还是这个数据   截断,因为我创建它们为动物?

法律 - 是的。数据不被截断(动物,狗或猫)

a)多态狗是一种动物,具有动物的所有方法和数据属性。

b)它还具有Dog的所有方法和属性。

实现是编译器特定的,但是一个典型的impl。是两个结构(有一些需要编译器注意的并发症)简单地连接在内存中。这首先不重要 - 这是一个实施问题。

cat和dog实例都可以访问自己的数据和方法属性,无论这些方法是否未映射到多态表。

此外,cat和dog实例都可以访问父动物实例中公共或受保护(但不是私有)的那些部分。

答案 1 :(得分:0)

我不确定我是否完全理解您的问题,但您的update()描述了虚拟函数调用。

我怀疑你在理解如何实现继承和多态方面遇到了问题,我知道我做到了。请考虑以下事项:

class base
{

private:
    int mylocalInt; //inaccessible to anyone but the base.

protected:
    int sharedInt = 5;//accessible by base, and any subtype.
public:

    base()
    {
        cout<<"creating base object"<<endl;
    }

    virtual ~base()
    {
        cout<<"Now destroying base object"<<endl;
    }

    void virtual callMe()//will be overridden, only called if you directly instantiate a base object.
    {
        cout<<"I am a base"<<endl;
    }

};

class subtypeA : public base
{
private:
    int Aint;
public:
    subtypeA()
    {
        cout<<"creating subtype"<<endl;
    }

    ~subtypeA()
    {
        cout<<"destroying subtype"<<endl;
    }

    void callMe()
    {
        cout<<"I am a subtypeA"<<endl;
    }

    int getAint()//this is a local, IE static function, a base ptr cannot access it.
    {
        return Aint;
    }

    int getSharedInt()//notice how sharedInt, located in the base object, is still accessible from within the subtype.
    {
        return sharedInt;
    }
};

int main(int argc, char* argv[] )
{
    base* ptr = new subtypeA;
    ptr->callMe();//works fine, will check which subtype, if any, ptr points to, and call the appropriate callMe(). This is because
                    //callMe() is virtual in base.
    //ptr->sharedInt//illegal, main is not part of base or a subtype of base.
    subtypeA* Aptr = (subtypeA*)ptr;//since all pointers are the same size, they can be cast to one another, is dangerous however
    cout<<Aptr->getSharedInt()<<endl;//works, getSharedInt is NOT virtual, but a normal static member of subtypeA, so in order to use it, the pointer
                                        //needs to be of type subtypeA. the sharedInt however is protected, so subtypeA can access it due to the fact that it is related to it's owner, base.

}

现在接受它,并使用它,添加一个subtypeB,然后将子类型添加到该子类型,例如IE subtypeAA和BB。

请注意,每个单独的类仍然是它自己的对象,不同于它所关联的任何对象。因此,如果变量是私有的,则无法从外部直接访问它,就像使用普通对象一样。

再说一遍:多态性没有什么特别之处,它只是一个很好的抽象,隐藏了“丑陋”的类型检查等等,以便进行虚拟调用。

我完全忘记了你的另一个问题。不,在这种情况下你永远不必担心截断。事实上,我前段时间或多或少地提出了相同的问题,请看一下:C++ subtype degeneration when placed in a container

dasblinkenlight非常出色地解释了它。