Can I use a variable on the same line that she declared in this factory in C ++?

I have a polymorphic class hierarchy. Although I also support the standard factory approach, where I use only base class pointers, I also need a factory mechanism that gives me derived classes, which is not so simple because these functions differ only in their return types. That's why I came up with the idea of ​​overloading a function and letting the compiler choose the right one.

A simple application is that I can write functions that create a derived object, "prepare" it, and return a base pointer to it for future access when type information is no longer needed.

  • Question 1: Is the following:
  • Question 2: The newObject () parameter is intended only for the compiler to select the correct function. I am worried about using p1the same line where it is declared. I have never read its value before setting it to newObject(), but I'm not sure if this can cause undefined behavior. I also have self-determination, because the return value is assigned to itself ...

This is a sample code:

class Base
{
  public:
    virtual ~Base(void){}
};

class Derived1 : public Base
{
  public:
    virtual ~Derived1(void){}
};

class Derived2 : public Base
{
  public:
    virtual ~Derived2(void){}
};

// factory

Base * newObject(int i)
{
    if (i == 1)
    {
        return new Derived1();
    }
    else
    {
        return new Derived2();
    }
}

// family of functions to create all derived classes of Base

Derived1 * newObject(Derived1 *& p)
{
    p = new Derived1();
    return p;
}

Derived2 * newObject(Derived2 *& p)
{
    p = new Derived2();
    return p;
}

int main()
{
    // compiler picks the right newObject function according to the parameter type
    Derived1 * p1 = newObject(p1);
    Derived2 * p2 = newObject(p2);

    // This is safe, right? But it does not convey that it creates something. Hence I prefer the above syntax.
    Derived2 * p3 = nullptr;
    newObject(p3);

    delete p3;
    delete p2;
    delete p1;
}

EDIT:

To get around the problem of using a newly created variable, this is an alternative:

Derived1 * newObject(Derived1 *)
{
    // anonymous variable is not used at all, just to pick the right function
    Derived1 * p = new Derived1();
    return p;
}
+2
source share
2 answers

This is a controversial design, but correct in terms of pure language. The C ++ standard has the following:

[basic.life]

1 - . , , , , . T , :

  • T
  • , ,

...

7 , , , , , gl, , ... glvalue glvalue , . undefined, :

  • glvalue
  • ...

7 , , , - UB.

1 , , . , , - 7.


newObject ( , ++ 11 auto p = newObject<Dervied1>()), ++ 11 , , , . :

namespace detail {
// ...
template<typename... Args>
struct DefferedConstruct {
    std::tuple<Args&...> args_tuple;

    template<typename T>
    operator T*() {
        return new T(make_from_tuple<T>(
            args_tuple
        ));
    }
};
} // namespace detail

template<typename... Args>
auto newObject(Args&&... args) -> detail::DefferedConstruct<Args...> {
    return detail::DefferedConstruct<Args...>{
        std::forward_as_tuple(args...)
    };
}

class Base
{
  public:
    virtual ~Base(void){}
};

class Derived1 : public Base
{
  public:
    Derived1(int) {}
    virtual ~Derived1(void){}
};

class Derived2 : public Base
{
  public:
    virtual ~Derived2(void){}
};

int main()
{
// compiler construct the right object according to the return type
    Derived1 *p1 = newObject(1);
    Derived2 *p2 = newObject();

    delete p1;
    delete p2;
}

++ , .

+4

, , , .

factory , , - ? , , , , , factory . :.

Derived1 * newDerived1() {
    return new Derived1();
}

Derived2 * newDerived2() {
    return new Derived2();
}

factory, :

template<
    typename T,
    typename = std::enable_if_t<std::is_base_of<Base, T>::value>
>
T* newObject() {
    return new T();
}

Derived1* d = newObject<Derived1>();

, , , , , .

, factory , . , .

+2

Source: https://habr.com/ru/post/1691546/


All Articles