我有一个类似于下面的代码示例的类型层次结构,并且我正在尝试通过工厂模式(或者,学究起来,而不是构建器模式,因为我的工厂从 XML 文档中获取输入......但我离题)。
但是我尝试这样做,我遇到了我怀疑是由于切片(如果我按值返回)或范围界定(如果我按引用返回)的问题。
例如,下面的程序在a.doA()
里面的行上有段错误C::doStuff()
。如果我将调用改为value_C_factory<C>()
改为ref_C_factory<C>()
,我会收到一些警告,即“返回对临时的引用”,但程序b.doB()
会在下一行编译、段错误(没有从a.doA()
...打印任何内容)。
回溯gdb
看起来像这样 - 第二行是我上面提到的代码中的那一行
#0 0x00007ffff7dbddb0 in vtable for std::ctype<char> () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00000000004010e9 in C::doStuff (this=0x7fffffffdd00) at syntax.cpp:57
#2 0x0000000000400cf2 in main () at syntax.cpp:95
是什么导致了这些段错误?正如我所怀疑的那样,它是在价值/参考案例中切片/范围吗?如果不是,那是什么?最重要的是,从输入数据构建实例的好方法是什么?
代码示例
下面的代码应该使用 GCC 4.8 编译并给出上述行为
gcc -g -Wall -std=c++11 -o test test.cpp
(这就是我所做的,无论如何)。
#include <iostream>
#include <typeinfo>
class IA {
public:
virtual void doA() const = 0;
virtual ~IA() { }
};
class A : public IA {
private:
std::string atask;
public:
explicit A(const std::string &task) : atask(task) {
std::cout << "Created A with task " << atask << std::endl;
}
void doA() const {
std::cout << "I did A! " << atask << std::endl;
}
};
class IB {
public:
virtual void doB() const = 0;
virtual ~IB() { }
};
class B : public IB {
private:
std::string btask;
public:
explicit B(const std::string &task) : btask(task) {
std::cout << "Created B with task " << btask << std::endl;
}
void doB() const {
std::cout << "I did B! " << btask << std::endl;
}
};
class IC {
public:
void doStuff() const;
virtual ~IC() { }
};
class C : public IC {
private:
const IA &a;
const IB &b;
public:
C(const IA &a, const IB &b) : a(a), b(b) { }
void doStuff() const {
a.doA(); // with value factory method, segfault here
b.doB(); // with reference factory, segfault here instead
}
};
template<typename TA>
TA value_A_factory() {
return TA("a value");
}
template<typename TB>
TB value_B_factory() {
return TB("b value");
}
template<typename TC>
TC value_C_factory() {
return TC(value_A_factory<A>(), value_B_factory<B>());
}
template<typename TA>
const TA &ref_A_factory() {
return TA("a ref");
}
template<typename TB>
const TB &ref_B_factory() {
return TB("b ref");
}
template<typename TC>
const TC &ref_C_factory() {
const TC &c(ref_A_factory<A>(), ref_B_factory<B>());
return c;
}
int main() {
C c = value_C_factory<C>();
std::cout << typeid(c).name() << std::endl;
c.doStuff();
}