如何避免对#define语法进行变量重新声明?

时间:2018-08-08 04:33:58

标签: c++ c-preprocessor

当我们在c ++中传递类类型的参数时,我们别无选择,只能使用#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); \

这是不可能的。有什么办法可以做到这一点?

3 个答案:

答案 0 :(得分:5)

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

#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技巧。 这几乎总是一种不好的做法,当然在您的情况下也是如此。

答案 1 :(得分:2)

  

当我们在c ++中传递类类型的参数时,我们别无选择,只能使用#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();
    }
}

答案 2 :(得分:1)

更改#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);
    // ...
}