C++ 压倒一切的几个基本问题

C++ 压倒一切的几个基本问题,c++,polymorphism,overloading,overriding,C++,Polymorphism,Overloading,Overriding,我的基本功没有什么问题,如果有人能帮我解决这个问题,我将不胜感激 1:我说base*b是什么意思 =新导出的;为什么有人会这么做?我们完全可以分开 为基类和类创建对象 类,然后调用 相应地发挥作用。我知道 这个基数*b=新的导出值;是 称为对象切片,但为什么和 什么时候可以买这个 2:我知道 为什么不建议转换 要派生的基类对象 类对象(因为基类是 不知道派生类 成员和方法)。我甚至在报纸上读过 其他StackOverflow线程,如果 情况就是这样,然后我们 必须更改/重新访问我们的设计。 我明

我的基本功没有什么问题,如果有人能帮我解决这个问题,我将不胜感激

1:我说base*b是什么意思 =新导出的;为什么有人会这么做?我们完全可以分开 为基类和类创建对象 类,然后调用 相应地发挥作用。我知道 这个基数*b=新的导出值;是 称为对象切片,但为什么和 什么时候可以买这个

2:我知道 为什么不建议转换 要派生的基类对象 类对象(因为基类是 不知道派生类 成员和方法)。我甚至在报纸上读过 其他StackOverflow线程,如果 情况就是这样,然后我们 必须更改/重新访问我们的设计。 我明白这一切,但是,我 只是好奇,有什么办法吗 这个

    class base
    {
    public:
        void f(){cout << "In Base";}
    };

    class derived:public base
    {
    public:
        void f(){cout << "In Derived";}
    };

    int _tmain(int argc, _TCHAR* argv[])
    {
        base b1, b2;
        derived d1, d2;
        b2 = d1;
        d2 = reinterpret_cast<derived*>(b1); //gives error C2440
        b1.f(); // Prints In Base
        d1.f(); // Prints In Derived
        b2.f(); // Prints In Base
        d1.base::f(); //Prints In Base
        d2.f();
        getch();
        return 0;
    }
类基
{
公众:
void f(){cout是和否。你可以走了
派生类:公共基{
public:void f(){base::f();}
};


但是,我不太确定是否在全局范围内。

问题1:为什么要这样做:您可能不会直接这样做。发生这种情况的情况是,例如,您有一个返回“某种基*”的函数,而您不关心它的类型

问题2:在派生中,您需要使用范围解析操作符来指定要使用基类的实现

注意:您尚未声明您的函数为虚拟函数,因此您实际上不会得到预期的行为

base *b = new derived
正在创建指向派生类对象的基类指针。这允许您创建is-a关系。派生类是基类。有关详细信息,请参阅

2
.d2=重新解释铸件(b1);
您正在尝试将基类对象转换为派生类对象。但所使用的强制转换操作不正确

若您计划调用基类方法,那个么就使用基类指针

Base* ptr = &b1;
ptr->f();

我建议您参考。

1。这不是对象切片:

base *b = new derived;
这是将类型为
base
的指针分配给
派生的
的实例

<>这个动作中的一个(非常常见的)例子是回调。考虑一下:

class Observer
{
public:
    virtual void OnEvent() = 0;
};

class Subject
{
public:
    Subject() : observer(0) {}
    void SetObserver(Observer* o) { observer = o; }
    void FireEvent() { if(observer != 0) observer->OnEvent(); }
private:
    Observer* observer;
};

class MyObserver : public Observer
{
public:
    void OnEvent() { ::printf("Hi there!\n"); }
};

int main()
{
    Subject s;
    MyObserver o;
    s.SetObserver(&o);
    s.FireEvent();
    return 0;
}
这应该是预期的输出:

你好

注意这里发生的事情。我们将一个指向
MyObserver
实例的指针传递到
SetObserver()
,即使该函数只接受
Observer
类型的指针。这是因为
MyObserver
(公开)派生自
Observer
。在本例中,我们说
MyObserver
是一个
观察者

Observer
类型定义了一个纯虚函数(
=0
表示该函数是纯函数;它必须由派生类实现。)
virtual
关键字告诉编译器调用该函数应该导致执行最派生的函数。
OnEvent()
MyObserver
中的
函数是最派生的,因此,即使我们在
Observer
类型的指针上调用
OnEvent()
,也会调用该版本

我们经历了这么多的麻烦,因为在这个代码中,
Subject
不需要知道它的观察者的确切类型-观察者只需要从
observer
派生,
Subject
实例将调用最派生类型的
OnEvent()实现
。这允许代码解耦-
主题
不依赖于
MyObserver
MyObserver
不依赖于
主题

2.将指针从基类型强制转换为派生类型本身并没有错。以下事实上是合法的,并保证有效:

class Base {};
class Derived : public Base {};

int main()
{
    Derived d;
    Base* bp = &d;
    Derived* dp = static_cast<Derived*>(bp);
    return 0;
}
如果
Foobar()
函数不是虚拟函数,则您将获得以下输出:

In Derived!
In Base!
In Derived!
In Derived!
否则,如果
Foobar()

In Derived!
In Base!
In Derived!
In Derived!
要确保对虚拟函数
Foobar()
的调用通过基指针调用基实现,则必须使用范围解析运算符:

// Prints "In Base!", even if bp actually points
// to an instance of Derived overriding Foobar().
bp->Base::Foobar();
(1) 您有一个指向派生类对象的基类指针。这是在实现多态性时使用的,在多态性中,您有几个派生类继承自一个公共基类。然后,您可以通过基类指针根据其类型调用正确的派生类函数,前提是该函数是虚拟的


class base
{
    public:
        virtual void f(){ cout << "In Base" << endl; }
};

class derived:public base
{
    public:
        void f(){ cout << "In Derived" << endl; }
};

class derived2: public derived
{
public:
    void f() { cout << "In Derived2" << endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    derived d1;
    derived2 d2;
    base* b;
    b = &d1;
    b->f();   // calls derived::f();
    b = &d2;
    b->f();   // calls derived2::f();
    return 0;
}
它也不称为对象切片。对象切片是指将派生类对象分配给基类对象(不是指针),其中派生类对象的成员被切片,因此无法从基类对象访问这些切片的成员

(2) 除了使用reinterpret_cast的行之外,其他语句都可以

(3) 如果使用对象或重写派生类函数来调用基类版本(如其他答案中所述),则必须使用范围解析运算符。但是,可以使用指针:

derived *d = static_cast( &b1 );
d->f();

请重新格式化以隔离代码。单击语法指南的小问号。感谢您清理了我的代码格式。我可以编辑我的问题吗/我没有看到任何编辑按钮。因为,从“我知道为什么不建议将基类对象转换为派生对象…”开始的语句是我的第二个问题,但它错误地附加到了第一个问题。大致修复了这个问题。您应该在问题下方看到一个编辑按钮。base*b=新派生;不是对象切片。对象切片发生在您按值赋值时,例如,base b=d;,其中d是派生的实例。“The
=0
表示函数是纯函数-它不存在”-不完全,表示派生
derived *d = static_cast( &b1 );
d->f();