【问题标题】:Is it possible to call a method from an instance that doesn't exist?是否可以从不存在的实例调用方法?
【发布时间】:2016-04-10 14:04:54
【问题描述】:

我正在处理的代码:

我有以下代码(ma​​in.cpp 中的索引有错误):

示例.hpp:

#ifndef SAMPLE_HPP
# define SAMPLE_HPP

# include <iostream>
# include <string>

class Sample{
public:
    Sample(void);
    ~Sample(void);
    void    tellname(void) const;
private:
    std::string     _name;
};

#endif

Sample.cpp:

#include <iostream>
#include "Sample.hpp"

Sample::Sample(void){
    this->_name = "testname";
    return;
};

Sample::~Sample(void){
    return;
}

void    Sample::tellname(void) const{
    std::cout << "Name : " << this->_name << std::endl;
    return;
}

main.cpp

#include "Sample.hpp"

int     main(void){
    int     i;
    Sample  *test;

    test = new Sample[4];
    i = 0;
    while (i++ < 4)          // I know : i++; shouldn't be here
        test[i].tellname();
    delete [] test;
    return 0;
}

如果我编译它,我会得到以下输出:

Name : testname
Name : testname
Name : testname
Name :

我的问题是:

关于最后一行,它调用了一个方法 (void Sample::tellname(void))但来自一个不在表格范围内的实例test[4] 不存在)。

但是,它仍然调用tellname(),即使它调用它的实例不存在。它只是认为它的_name 字段为空。

这怎么可能?

【问题讨论】:

标签: c++


【解决方案1】:

i 从 1 到 4 包含,因为 tellname 是 const,test[4].tellname()Sample::tellnameSample 是一个未定义的结构,因此“名称:”被正确打印,然后内存在 test[4]._name被打印出来,幸运的是test[4]._name*指向的内存不是空的,甚至是一个结束字符串char。

是的,你很幸运。

【讨论】:

  • 您好 88877,欢迎来到 SO。请让代码保持其格式,用反引号 (`) 将其括起来或用四个空格填充开头。您可以使用 CTRL-K 或 {} 按钮自动执行此操作。
【解决方案2】:

听起来您想知道为什么调用该函数。在内存中,结构不包含其中的函数。相反,函数的一份副本被放置在可执行文件的某处。所以当你调用test[4].tellname() 时,真正发生的是:地址test + (4 * sizeof(Sample)) 被传递给函数tellname()。该地址的值未定义。

下面是一个示例,让您了解正在发生的事情:

#include <iostream>

struct astruct {
    int i = 0;
    void prnt()
    {
        std::cout << i << '\n';
    }
};

struct bstruct {
    int y = 100;
};

int main()
{
    bstruct b;
    ((astruct*)&b)->prnt();
    getchar();
    return 0;
}

这里 prnt() 在幕后传递 bstruct 的地址并将其视为 astruct 的地址,因为 bstruct 中的第一个值是 100,它打印 100。您甚至可以将其简化为:

#include <iostream>

struct astruct {
    int i = 0;
    void prnt()
    {
        std::cout << i << '\n';
    }
};

int y = 100;

int main()
{
    ((astruct*)&y)->prnt();
    getchar();
    return 0;
}

【讨论】:

  • 有趣,但它与结构无关。但我想这几乎是一样的?
  • 类和结构基本上是一回事。类成员默认是私有的,结构成员默认是公有的。
【解决方案3】:

这只是未定义的行为,C++ 对“任何事情都可能发生”没有任何要求。你所看到的只是一个巧合,毫无价值:下次你运行它可能会崩溃,显示 nyan cat 等等。

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多