如何避免#define 语法的变量重新声明?

How can I avoid variable re-declaration for #define syntax?

当我们在c++中传递class类型的参数时,我们不得不使用#define。 但这会使代码变得混乱。

#include <vector>
#define APPEND(className) \
        base = new className(); \
        baseVector.push_back(base); \

class Base{};
class Child1 : public Base{};
class Child2 : public Base{};
// ...
class Child10 : public Base{};
std::vector<Base*> baseVector;
int main(void){
    Base* base; // I want to remove this
    APPEND(Child1);
    APPEND(Child2);
    // ...
    APPEND(Child10);
}

如果我将 Base* base 放在#define 语法中,则会发生重新声明错误。 但是,如果我只是让它看起来很尴尬。

#define APPEND(className) \
        #ifndef DECL \
        Base* base; \
        #define DECL \
        #endif \
        base = new className(); \
        baseVector.push_back(base); \

这是不可能的。有什么办法可以实现吗?

首先,您的代码甚至无法编译。这是固定版本:

#include <vector>

class Base{};

class Child1 : public Base {};
class Child2 : public Base {};

std::vector<Base*> baseVector;

int main(void)
{
    baseVector.push_back( new Child1 );
    baseVector.push_back( new Child2 );

    return 0;
}

您绝对不需要任何 #define 技巧。 这几乎总是不好的做法,当然在你的情况下也是如此。

#define的代码换成自己的一组括号,这样每次调用push_back().

时都可以声明自己的局部变量

试试像这样的东西:

#include <vector>

#define APPEND(className) \
{ \
    Base *base = new className(); \
    try { \
        baseVector.push_back(base); \
    } catch (...) { \
        delete base; \
        throw; \
    } \
}

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

class Child1 : public Base {};
class Child2 : public Base {};
// ...
class Child10 : public Base {};

std::vector<Base*> baseVector;

int main(void){
    APPEND(Child1);
    APPEND(Child2);
    APPEND(Child3);
    // ...
    APPEND(Child10);
    // ...
}

When we pass parameter of class type in c++, we have no choice but to use #define.

我们有选择。我们可以使用模板:

#include <vector>
#include <iostream>

using namespace std;

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

class Child1: public Base {
    void hello() { cout << "Child1" << endl; }
};

class Child2: public Base {
    void hello() { cout << "Child2" << endl; }
};

class Child3: public Base {
    void hello() { cout << "Child3" << endl; }
};

vector<Base*> baseVector;

template<typename T>
void append() {
    Base* child = new T{};

    try {
        baseVector.push_back(child);
    } catch (...) {
        delete child;
        throw;
    }
}

int main(void)
{
    append<Child1>();
    append<Child2>();
    append<Child3>();

    for (auto child : baseVector) {
        child->hello();
    }

    for (auto child : baseVector) {
        delete child;
    }
}

但是你应该避免使用 newdelete 运算符,而只使用智能指针:

#include <vector>
#include <iostream>
#include <memory>

using namespace std;

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

class Child1: public Base {
    void hello() { cout << "Child1" << endl; }
};

class Child2: public Base {
    void hello() { cout << "Child2" << endl; }
};

class Child3: public Base {
    void hello() { cout << "Child3" << endl; }
};

vector<unique_ptr<Base>> baseVector;

int main(void){
    baseVector.push_back(make_unique<Child1>());
    baseVector.push_back(make_unique<Child2>());
    baseVector.push_back(make_unique<Child3>());

    for (auto& child : baseVector) {
        child->hello();
    }
}