构造函数 Foo::Foo 接收对 Foo 的引用,但不接收复制构造函数

发布于 2024-10-13 21:38:29 字数 1642 浏览 9 评论 0原文

假设我有一个不可复制Foo, 并且它的构造函数之一恰好收到了对 Foo 的引用。

class Foo
{
public:
    Foo(Foo& parent) {...}

private:
    void operator=(Foo); // disabled
    ...
};

编译器认为这是一个复制构造函数, 虽然它做了一些与复制完全无关的事情(因此赋值运算符被禁用)。

以这种方式定义构造函数有什么危险吗? 或者我应该人为地改变它的签名,例如使用指针而不是引用, 或者添加一个强制性的虚拟参数?

这是一些背景信息(可能不需要理解/回答我的问题)。

我有一个我自己编写的类库, 它充当用户代码和另一个库之间的连接。 另一个库提供了一项服务,为简洁起见,我将其称为“frobnicate”。 用户代码可以如下所示:

class UsefulObject: public mylib::Frobnicator
{
    ...
    void DoStuff()
    {
        int x = ...
        ...
        frobnicate(x); // it's important to allow simple syntax here
        frobnicate(x + 1);
        ...
    }
    ...
};

我想支持用户对象的层次结构:每个对象都包含在另一个对象(其父对象)中, 虽然有一些(在我的例子中是 5 个)顶级对象包含所有其他对象。

每个对象都有一个日志文件;我希望每个呼叫都记录在多个日志文件中, 沿着包含层次结构向上直到顶级对象。

我是这样实现的:

namespace mylib
{
    class Frobnicator // provides the frobnication service
    {
    public:
        Frobnicator(Frobnicator& parent): parent(parent) {}
    protected:
        virtual void frobnicate(int x) {
            ... // some logging code
            parent->frobnicate(x);
        }
    private:
        Frobnicator& parent;
    };

    namespace internal // users of mylib, please don't use this!
    {
        class TheUltimateFrobnicator: public Frobnicator
        {
        protected:
            virtual void frobnicate(int x) {
                the_other_library::frobnicate(x);
            }
        private:
            TheUltimateFrobnicator(int id); // called by a factory or some such
        };
    }
}

Suppose i have a non-copyable class Foo,
and one of its constructors just happens to receive a reference to Foo.

class Foo
{
public:
    Foo(Foo& parent) {...}

private:
    void operator=(Foo); // disabled
    ...
};

The compiler thinks that this is a copy-constructor,
while it does something entirely unrelated to copying (so the assignment operator is disabled).

Is there any danger in defining the constructor this way,
or should i change its signature artificially, e.g. use pointer instead of reference,
or add a mandatory dummy parameter?

Here is some context (probably not required to understand/answer my question).

I have a class library that i have written myself,
which serves as a connection between user code and another library.
The other library provides a service that i call frobnicate for brevity.
User code can look like this:

class UsefulObject: public mylib::Frobnicator
{
    ...
    void DoStuff()
    {
        int x = ...
        ...
        frobnicate(x); // it's important to allow simple syntax here
        frobnicate(x + 1);
        ...
    }
    ...
};

I want to support an hierarchy of user objects: each object is contained in another (its parent),
while there are a few (in my case, 5) top-level objects that contain every other objects.

Each object has a log-file; i want each call to be logged in several log files,
up the containment hierarchy until a top-level object.

I have it implemented this way:

namespace mylib
{
    class Frobnicator // provides the frobnication service
    {
    public:
        Frobnicator(Frobnicator& parent): parent(parent) {}
    protected:
        virtual void frobnicate(int x) {
            ... // some logging code
            parent->frobnicate(x);
        }
    private:
        Frobnicator& parent;
    };

    namespace internal // users of mylib, please don't use this!
    {
        class TheUltimateFrobnicator: public Frobnicator
        {
        protected:
            virtual void frobnicate(int x) {
                the_other_library::frobnicate(x);
            }
        private:
            TheUltimateFrobnicator(int id); // called by a factory or some such
        };
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡忘如思 2024-10-20 21:38:29

不幸的是,这种构造函数的含义似乎存在歧义。我认为消除歧义的最直接方法是使用指针,

class Frobnicator // provides the frobnication service
{
public:
    explicit Frobnicator(Frobnicator *parent): parent(parent) {}
protected:
    virtual void frobnicate(int x) {
        ... // some logging code
        parent->frobnicate(x);
    }
private:
    void operator=(Foo); // disabled
    Frobnicator(Frobnicator const&); // disabled

    Frobnicator *parent;
};

我知道很多人无论如何都希望参数是指针。顺便说一句,您自己将 parent.frobnicate 错误地输入为 parent->frobnicate

This appears to be an unfortunate ambiguity in the meaning of such a constructor. I think the most straight forward way to disambiguate this is to use a pointer

class Frobnicator // provides the frobnication service
{
public:
    explicit Frobnicator(Frobnicator *parent): parent(parent) {}
protected:
    virtual void frobnicate(int x) {
        ... // some logging code
        parent->frobnicate(x);
    }
private:
    void operator=(Foo); // disabled
    Frobnicator(Frobnicator const&); // disabled

    Frobnicator *parent;
};

I know a lot of people who would expect the parameter to be a pointer anyway. Incidentally, you yourself mistyped parent.frobnicate as parent->frobnicate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文