抽象类和丢失信息

Abstract Classes and Losing Information

本文关键字:信息 抽象类      更新时间:2023-10-16

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

假设我们有一个名为 Animal 的抽象类,以及实现该类的名为 Cat and Dog 的类。这两个类都实现了来自 Animal 的一个名为 update() 的方法;但是,在他们的更新方法中,他们访问私有方法和/或变量,这些方法和/或变量是独占的,而不是 Animal 类。我知道如果我们以这种方式声明类......

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

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

该语言不会强制您仅使用对方法"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() 

。我们只能访问只有动物的方法或变量 类具体有;

我同意。。。 狗是一种动物,没有方法Bark,因此无法调用dog->bark()。 但是,你可以向这三个方法添加一个方法"virtual void talk()",也许虚拟void Dog::talk()会简单地调用它的本地Dog::bark()方法,而Cat::talk()会简单地调用它的本地Cat::meow()方法。

但是,如果我在每个类上调用 update() 方法怎么办, 而这个更新方法调用独占的 《猫与狗》中的成员。这是合法的,还是这些数据是合法的 被截断是因为我将它们创建为动物?

法律 - 是的。 数据不会被截断(在动物、狗或猫中)

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

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

实现是特定于编译器的,但一个典型的 impl. 是这两个结构(有一些需要编译器注意的复杂性)只是在内存中连接起来。 哪个是第一个并不重要 - 这是一个实现问题。

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

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

不确定我是否完全理解您的问题,但是您的 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.
}

现在拿起它,并尝试它,添加一个子类型B,然后将子类型添加到该子类型,例如IE子类型AA和BB。

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

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

我完全忘记了你的另一个问题。不,在这种情况下,您永远不必担心截断。其实我前段时间问了或多或少同样的问题,看看:C++亚型放在容器中时退化

达斯布林肯莱特出色地解释道。