我有两个类:
class A{
private:
int a;
public:
void display()
{
cout<<"A: "<<a;
}
A()
{
a=10;
}
};
class B: public A
{
private:
int b;
public:
void display1()
{
cout<<"B: "<<b;
}
B()
{
b=15;
}
};
A *a= new B
和B *b = new B
有什么区别?对象b
可以访问两个类A
和B
的成员,而对象a
只能访问类A的成员。然而,在以下给出的虚拟析构函数示例中:没有虚拟构造函数,但虚拟析构函数或任何其他示例,它总是显示基类创建派生类的对象。为什么这会有用?当 obj a
只能访问class A
的成员时,创建class B
对象有什么需要?
我无法为此想出一个实际的例子。
我无法为此想出一个实际的例子。
它被称为多态性,它可以说是OOP最重要的方面。基类可以使用虚函数定义接口;派生类可以重写这些函数以提供它们喜欢的任何行为。用户可以与基类交互,而不了解派生类,并且仍然可以使用派生类的功能。
为了提供一个示例,只需更改基类以声明一个虚拟函数:
virtual void display() {cout << "An";}
并更改派生类以覆盖它,而不是声明具有不同名称的不相关函数:
void display() override {cout << "Bn";}
现在我们可以看到 A 类型的对象之间的区别:
A a;
a.display(); // prints A
以及类型 B 之一,即使通过指针或对 A 的引用访问:
B b;
A & a = b;
a.display(); // prints B
想象一下这个应用程序。您有一个形状类(基(和两个矩形和trangle类(派生(。如何从基类函数计算每个形状的面积。
class shape {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
//look this method is virtual and is implemented in derived classes
virtual int area ()
{ return 0; }
};
class Rectangle: public shape {
public:
int area ()
{ return width * height; }
};
class Triangle: public shape {
public:
int area ()
{ return (width * height / 2); }
};
用法
shape* s1 = new Rectangle();
shape* s2 = new Triangle();
//set values accordingly
然后你可以调用area
函数,看看哪些方法会调用......
s1->area(); //area method of rectangle class
s2->area(); // area method of tangle class
希望你明白了。
这是一个从外部访问的问题。虽然a
允许用户只访问A
的界面,但b
允许用户也访问B
的界面。你似乎已经明白这部分了。
你的第三个问题需要另一个比较:A *a = new B;
和A *a = new A;
有什么区别?这里的区别在于,在第一个示例中,A
中的所有虚拟方法都被 B
的"替换"。这称为专业化。虽然你使用超类A
更通用的接口,运行时的实现是B
虚方法的。由于这些方法通常依赖于B
的数据结构,因此必须实例化类B
的对象。
A* a = new B;
以及
B* b = new B;
在堆上创建一个对象。在第一种情况下,可以通过指针a
访问A
中定义的函数。如果A
有任何virtual
函数并且它们是在B
中实现的,那么在a
上调用这些函数最终将调用B
中的函数。a
上的任何非virtual
函数调用都将调用 A
中定义的函数。
在第二种情况下,可以通过指针b
访问B
中定义的函数以及A
中定义的函数。
在您的情况下,您可以使用:
a->display();
以及
b->display();
您可以使用
b->display1();
但你不能使用
a->display1();
如果将display()
和display1()
替换为虚拟函数,例如:
class A
{
public:
virtual display() { ... }
};
class B : public A
{
public:
virtual display() { ... }
};
然后,呼叫
a->display();
最终会打电话给B::display()
.