下面的情况是静态的还是动态的?因为我知道,我的指针在编译时指向的对象的类是什么,我猜它是静态的.
class Base
{
void print() const;
};
class Derived : public Base
{
void print() const;
};
int main()
{
Base base;
Base *basePtr = &base;
basePtr->print();
}为什么我们应该使用动态绑定而不是静态呢?我不明白为什么我们应该使用虚拟函数,而不是以这种方式调用函数base.print() (对于上面的例子)。这个方法已经“理解”了print()函数调用对象的正确类,而不使用多态和虚拟函数。
更新
// Point class definition represents an x-y coordinate pair.
#ifndef POINT_H
#define POINT_H
class Point {
public:
Point( int = 0, int = 0 ); // default constructor
void setX( int ); // set x in coordinate pair
int getX() const; // return x from coordinate pair
void setY( int ); // set y in coordinate pair
int getY() const; // return y from coordinate pair
virtual void print() const; // output Point object
private:
int x; // x part of coordinate pair
int y; // y part of coordinate pair
}; // end class Point
#endif // Circle class contains x-y coordinate pair and radius.
#ifndef CIRCLE_H
#define CIRCLE_H
#include "point.h" // Point class definition
class Circle : public Point {
public:
// default constructor
Circle( int = 0, int = 0, double = 0.0 );
void setRadius( double ); // set radius
double getRadius() const; // return radius
double getDiameter() const; // return diameter
double getCircumference() const; // return circumference
double getArea() const; // return area
virtual void print() const; // output Circle object
private:
double radius; // Circle's radius
}; // end class Circle
#endif // Introducing polymorphism, virtual functions and dynamic
// binding.
#include <iostream>
using std::cout;
using std::endl;
using std::fixed;
#include <iomanip>
using std::setprecision;
#include "point.h" // Point class definition
#include "circle.h" // Circle class definition
int main()
{
Point point( 30, 50 );
Point *pointPtr = 0;
Circle circle( 120, 89, 2.7 );
Circle *circlePtr = 0;
// set floating-point numeric formatting
cout << fixed << setprecision( 2 );
// output objects point and circle using static binding
cout << "Invoking print function on point and circle "
<< "\nobjects with static binding "
<< "\n\nPoint: ";
point.print(); // static binding
cout << "\nCircle: ";
circle.print(); // static binding
// output objects point and circle using dynamic binding
cout << "\n\nInvoking print function on point and circle "
<< "\nobjects with dynamic binding";
// aim base-class pointer at base-class object and print
pointPtr = &point;
cout << "\n\nCalling virtual function print with base-class"
<< "\npointer to base-class object"
<< "\ninvokes base-class print function:\n";
pointPtr->print();
// aim derived-class pointer at derived-class
// object and print
circlePtr = &circle;
cout << "\n\nCalling virtual function print with "
<< "\nderived-class pointer to derived-class object "
<< "\ninvokes derived-class print function:\n";
circlePtr->print();
// aim base-class pointer at derived-class object and print
pointPtr = &circle;
cout << "\n\nCalling virtual function print with base-class"
<< "\npointer to derived-class object "
<< "\ninvokes derived-class print function:\n";
pointPtr->print(); // polymorphism: invokes circle's print
cout << endl;
return 0;
} // end main发布于 2014-05-08 13:27:39
下面的情况是静态的还是动态的?
静态的,因为函数不是虚拟的。
如果它是虚拟的,那么该函数将根据对象的动态类型进行分派。
为什么我们应该使用动态绑定而不是静态呢?
当我们想要通过公共基类与不同类型的对象交互时,不知道实际(动态)类型是什么。例如,
class Base
{
virtual void print() const; // add "virtual" to enable dynamic dispatch
};
// This function doesn't know the real (dynamic) type of the object,
// but still calls the correct version of "print".
void print(Base const & base) {
// If "print" is virtual, then this calls the override for the dynamic type.
// Otherwise, this calls Base::print.
base.print();
}
int main() {
Base base;
Derived derived;
print(base); // calls Base::print
print(derived); // calls Derived::print
}这个方法已经“理解”了print()函数调用对象的正确类,而不使用多态和虚拟函数。
实际上,如果您已经知道了动态类型,那么多态性就没有用了。它用于当您不知道动态类型时,如我的示例所示。
发布于 2014-05-08 13:25:31
在您的示例中没有任何动态绑定。您只需定义基类类型的指针,并为其分配(相同)基类对象的地址。因此,尚不清楚为什么要讨论动态绑定。
此外,派生类的定义也在这里使用。
当指针或引用的静态类型与其动态类型不协同时,以及在使用虚拟函数时,使用动态绑定。在您的示例中,没有第一个要求,也没有第二个要求。
下面是一个动态绑定的示例
#include <iostream>
class Base
{
virtual void print() const { std::cout << "Base" << std::endl; }
virtual ~Base() = default;
// or virtual ~Baae() {}
};
class Derived : public Base
{
void print() const { std::cout << "Derived" << std::endl; }
};
int main()
{
Derived d;
Base *basePtr = &d;
basePtr->print();
}虽然静态类型的指针basePtr是Base *,但是它的动态类型是Derived *,因为它是由派生类的一个对象的地址分配的。
引用C++标准中的一条说明是有用的,因为它会更清楚
示例:如果静态类型为“指向B类的指针”的指针(8.3.1) p指向从B派生的D类对象(第10条),则表达式*p的动态类型为“D”。引用(8.3.2)被类似地对待。-end实例
发布于 2014-05-08 13:25:47
使用virtual方法时会发生动态绑定。Base::print不是virtual。动态绑定的思想是在运行时将被调用的实际方法绑定,当derived类重写基类中的virtual方法时发生这种情况,然后根据实际对象类(基类/派生),方法得到绑定。实际上,在与基类同名的派生类中定义方法会隐藏基类方法,这是一种不好的做法。
https://stackoverflow.com/questions/23542663
复制相似问题