将临时对象作为对抽象的引用传递给构造函数 [英] Passing temporary object as a reference to an abstract to a constructor

查看:56
本文介绍了将临时对象作为对抽象的引用传递给构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对C ++有点生疏,遇到了一些麻烦。

I'm a bit rusty on my C++ and have run into a bit of a snag.

我有一个类,例如 user 为其构造函数引用一个抽象类。理想情况下,我希望该类支持以下语法:

I have a class, in the example user which takes a reference to an abstract class for its constructor. Ideally, I'd like for the class to support the following syntax:

User u( Sub("") );
u.work();

我有一个抽象类 super 基本类称为 sub user 类在其构造函数中引用了super。在运行时,用户传递了对 sub 的临时引用。

I have an abstract class super with a base class called sub. The user class takes a reference to super in its constructor. At runtime, user is passed a temporary reference to sub.

调用 u.work()时出现异常-因为临时目录已被解构。 (奇怪的是,如果删除 super sub 上的析构函数,我会得到不同的行为。)

When u.work() is called I get an exception - because the temporary has been deconstructed. (Oddly enough I get a different behaviour if I remove the destructors on super and sub).

下面的示例代码!

是否可以解决此问题?

我知道如果我接受更改签名并在呼叫站点更改语法的方式很多,但是我更喜欢保留调用签名:

I know there are lots of ways if I accept to change the signature and change the syntax at the call site, but I'd prefer to hold on to the calling signature:

User u( Sub("") );
u.work();

示例代码

class Super {
public:
    Super()
    {
        std::cout << __FUNCTION__ << std::endl;
    };

    virtual ~Super()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    virtual void func() = 0;
};

class Sub : public Super
{
public:
    Sub(char* name) :
        name_(name)
    {
        std::cout << __FUNCTION__ << std::endl;
    };

    virtual ~Sub()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    virtual void func()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    char* name_;
};

class User
{
public:
    User(Super& s) :
        super_(s)
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    ~User()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    void work()
    {
        std::cout << __FUNCTION__ << std::endl;
        super_.func();
    }

    Super& super_;
};

int main()
{
    User u( Sub("") );
    u.work();
    return 0;
}


推荐答案

临时对象的生存期就像您的 Sub()终止于它所在的完整表达式的末尾,即分号。

The lifetime of a temporary object like your Sub("") ends at the end of the full-expression in which it appears, i.e. at the semicolon.

C ++不允许您将此类临时对象绑定到可变引用,但是Microsoft的编译器允许这样做。但是,从这样的临时值初始化类成员引用会立即产生一个悬空引用,您永远不能再使用它。

C++ doesn't allow you to bind such temporary objects to mutable references, but Microsoft's compiler does allow that. Nonetheless, initializing a class member reference from such a temporary value immediately produces a dangling reference, which you must never ever use again; evaluating it outside the constructor body results in undefined behaviour.

解决此问题的方法是不在类中存储引用!

The way to fix this is to not store references in your class!

例如,如果要拥有一个多态值,则可以使用唯一的指针:

For example, if you wanted ownership of a polymorphic value, you could use a unique pointer:

 #include <memory>

 class User
 {
    std::unique_ptr<Super> s_;

 public:
    User(std::unique_ptr<Super> s) : s_(std::move(s)) {}

    void work() { s_->func(); }
 };

 User u(std::make_unique<Sub>("Hello"));
 u.work();

这篇关于将临时对象作为对抽象的引用传递给构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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