我有一个关于从抽象类创建类以及如何剪切数据的问题。
假设我们有一个名为 Animal 的抽象类,以及实现所述类的名为 Cat 和 Dog 的类。这两个类都实现了一个名为 update()的 Animal 方法;但是,在他们的更新方法中,他们访问私有方法和/或变量,这些方法和/或变量是自己独有的,而不是Animal类。我明白,如果我们以这种方式宣布课程......
Animal* dog = new Dog();
Animal* cat = new Cat();
我们只能访问只有Animal类特有的方法或变量;但是,如果我在每个类上调用 update()方法,并且此更新方法调用Cat和Dog中的独占成员,该怎么办?这是合法的,还是会因为我将它们创建为动物而被截断?
答案 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非常出色地解释了它。