C ++将此代码与多态性,指针和对象切片混淆 [英] C++ Confused by this code with polymorphism, pointers and object slicing

查看:104
本文介绍了C ++将此代码与多态性,指针和对象切片混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解多态性,对象切片和指针在此代码块中的工作方式.我正在Visual Studio中工作.

I'm trying to understand how polymorphism, object slicing and pointers work in this block of code. I'm working in Visual Studio.

#include <iostream>

class Man {
public:

    virtual void speak() { std::cout << "I'm a man." << "\n"; }

private:

};

class Soldier : public Man {
public:

    virtual void speak() { std::cout << "I'm a soldier." << "\n"; }

private:

};

int main() {

    Man man1;
    Soldier soldier1;

    man1 = soldier1;
    std::cout << "Man1: "; man1.speak();

    Man *man2 = new Man;
    Man *soldier2 = new Soldier;

    man2 = soldier2;
    std::cout << "Man2: "; (*man2).speak();

    Man *man3 = new Man;
    Soldier *soldier3 = new Soldier; // "Man *soldier3 = new Soldier;" will give the same output.

    *man3 = *soldier3;
    std::cout << "Man3: "; man3->speak();

    return 0;

}

输出为:

Man1: I'm a man.
Man2: I'm a soldier.
Man3: I'm a man.

我进行了一些搜索,并了解了对象切片"的概念.我猜那正是man1和man3发生的事情.但是,等等,我们不是在所有这些类中都使用了关键字"virtual"吗?难道man1和* man3首先不应该找出它们各自是什么类的对象,然后调用特定的最重要的talk()吗?

I did some searching and learned about the concept "object slicing". I guess that is what has happened to man1 and man3. But wait, didn't we use the keyword "virtual" in all of those classes? Shouldn't man1 and *man3 first find out what class of object they each are, and call the specific overriding speak()?

还是因为切片已经在=运算符的以下行进行了

Or is it because slicing has already happened at the = operator, at the line:

man1 = soldier1;

行:

*man3 = *soldier3;

而man1和* man3现在真的只是Man对象吗?

And man1 and *man3 are really just Man objects now?

另一个编码人员猜测这是因为=运算符仅将右侧值分配给左侧变量的副本.仍然需要确认.

A fellow coder guessed it is because the = operator is only assigning the right-hand-side value to a copy of the left-hand-side variable. It needs to be confirmed still.

除此之外,我要实现的目标是将Soldier对象复制到另一个内存地址,这与在man2和士兵2的情况下如何将两个指针指向同一内存地址不同.

Aside from those, the goal I want to achieve is to copy that Soldier object to a different memory address, unlike how I point two pointers at one same memory address, in the case of man2 and soldier2.

最后,我想知道为什么切片不会在第2部分中发生,以及像这样的语法真正发生了什么:

Finally, I wonder why slicing doesn't happen in part2, and what really happens at syntax like this:

Man *soldier2 = new Soldier;

严重的是它是做什么的..?

Seriously what does it do..?

我对此表示感谢.我是一名基本的C ++程序员:)<

I appreciate any insight on this. I'm a basic C++ programmer :) <

推荐答案

我们不是在所有这些类中都使用关键字虚拟"

didn't we use the keyword "virtual" in all of those classes

virtual关键字与对象切片无关.

The virtual keyword is unrelated to object slicing.

man1和* man3不应该首先找出它们各自是什么类的对象,然后调用特定的覆盖的say()吗?

Shouldn't man1 and *man3 first find out what class of object they each are, and call the specific overriding speak()?

不,他们不能,而且不应该. C ++具有一定的对象模型.它包括占据一定内存区域的对象.在该模型中没有对象分配可以像您期望的那样工作的地方.

No, they cannot and they should not. C++ has a certain object model. It includes objects occupying a certain region of memory. There's no place in this model for object assignment working like you expected it to work.

将此修改考虑为士兵的职业:

Consider this modification to a soldier class:

class Soldier : public Man {
public:

    virtual void speak() { std::cout << "I'm a soldier with a" << weapon << "\n"; }

    Soldier (const std::string& w) : weapon(w) {}

private:

    std::string weapon;

};

现在,您有Soldier个对象比Man个对象占用更多的空间.分配时

Now you have Soldier objects occupying more space than Man objects. When you assign

man1 = soldier1

man1内根本没有适合武器线的地方,因此它被切断了.现在,士兵的speak无法工作,因为它无法找到武器,因此使用了人类的speak.

there's simply no place inside man1 to fit the weapon string, so it gets cut off. Now soldier's speak cannot possibly work because it would not be able to find the weapon, so man's speak is used.

分配指针时,不会中断,因为Man指针完全能够指向Soldier.在原始内存级别,所有指针本质上都是相同的,并且它们并不关心要指向的内容.这就是为什么多态可以起作用的原因.

When you assign pointers, there's no cut off because a Man pointer is perfectly capable of pointing to a Soldier. At the raw memory level all pointers are essentially the same and they don't care what to point at. This is why polymorphism can work.

一些人(包括我自己)会认为,由于对象切片几乎总是一个错误,因此尝试调用它应该会导致编译时错误,而不是使无声破坏变得混乱.但是该语言目前尚未以这种方式定义,因此您必须提防.

Some (including myself) would argue that since object slicing is almost always an error, an attempt to invoke it should cause a compile-time error rather than confusing silent breakage. But the language isn't currently defined this way, so you have to watch out.

这篇关于C ++将此代码与多态性,指针和对象切片混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆