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

1 :当我说base * b时是什么意思
=新派生;为什么要为此呢?我们很好可以分开
为类库创建对象并
类派生,然后调用
相应地起作用。我知道
这个基* b =新派生的;是
称为对象 slice ,但是为什么和
一个人什么时候会去呢?

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;
    }

3:在上面的示例中,有什么方法可以使用派生类对象调用基类f()?我使用了d1.base():: f()我只是想知道是否有任何不使用范围解析运算符的方法?

非常感谢您抽出宝贵的时间来帮助我!

最佳答案

1. 这不是对象 slice :

base *b = new derived;

这是将base类型的指针分配给derived的实例。

回调的一个例子(很常见)。考虑一下:
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是-an Observer
Observer类型定义了一个纯虚函数(=0表示该函数是纯虚函数;它必须由派生类实现)。关键字virtual告诉编译器,调用该函数应导致执行派生最多的函数。 OnEvent()中的MyObserver函数是派生最多的函数,因此,即使我们在OnEvent()类型的指针上调用Observer,也会调用该版本。

我们会经历所有这些麻烦,因为在此代码中Subject不必知道其观察者的确切类型-观察者只需从Observer派生,并且Subject实例将调用派生率最高的OnEvent()的实现。这允许代码解耦-Subject不依赖MyObserver,而MyObserver不依赖Subject

2. 将指针从基本类型强制转换为派生类型本身没有任何问题。以下内容实际上是合法的,可以保证正常工作:
class Base {};
class Derived : public Base {};

int main()
{
    Derived d;
    Base* bp = &d;
    Derived* dp = static_cast<Derived*>(bp);
    return 0;
}

但是,此代码段中return语句之前的行是未定义的:
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};

int main()
{
    Derived1 d1;
    Base* bp = &d1;
    Derived2* d2p = static_cast<Derived2*>(bp); // WTF?!
    return 0;
}
d2p指针的值毫无意义,尝试访问其中的任何内容肯定会导致崩溃,因为bp指针实际上并未指向Derived2实例,而是指向了Derived1实例。编译器无法在编译时捕获此错误,因为Derived1Derived2均继承自Base,因此强制转换成功编译。这是从基本类型转换为派生类型的主要危险-您要等到运行时类型转换才能真正返回有意义的结果。

当然,除非使用dynamic_cast<>(),否则强制转换会导致运行时损失。 static_cast<>()最多涉及指针算术。 reinterpret_cast<>()强制指针采用其他(可能不相关)的类型,而不执行任何指针算术。这使reinterpret_cast<>()成为更危险的强制转换之一,仅在必要时才应使用,尤其是在static_cast<>()可以胜任的情况下。

3. 请考虑以下事项:
class Base
{
public:
    void Foobar() { ::printf("In Base!\n"); }
};

class Derived : public Base
{
public:
    void Foobar() { ::printf("In Derived!\n"); }
};

int main()
{
    Derived d;
    Derived* dp = &d;
    Base* bp = dp;
    dp->Foobar();
    bp->Foobar();
    return 0;
}

如果Foobar()函数不是虚拟的,那么您将获得以下输出:
In Derived!
In Base!

否则,如果Foobar()函数是虚拟的,那么您将获得以下输出:
In Derived!
In Derived!

为了确保对虚拟函数Foobar()的调用通过基本指针调用基本实现,则必须使用范围解析运算符:
// Prints "In Base!", even if bp actually points
// to an instance of Derived overriding Foobar().
bp->Base::Foobar();

10-04 14:31