我如何从一个 class 继承,因为我覆盖了一个函数而无法用某些模板参数实例化?
How can I inherit from a class that can't be instanciated with certain template parameters because of a function that I'm overriding?
我有一些类似于下面的代码:
#include <type_traits>
template <typename T>
class A
{
virtual void failifint()
{
static_assert(!std::is_same<T, int>(), "T is an int!");
}
};
class B : public A <int>
{
virtual void failifint()
{
// Don't fail
}
};
int main()
{
B b ;
}
我希望任何包含 A<T>
对象的代码只要 T
不是 int
就可以编译,而包含 B
的代码编译,因为 failifint()
被覆盖为 int 可编译版本。但是,上述代码由于静态断言而失败,即使没有任何 A<int>
实例化。
为什么会这样?以及如何使用 failifint
的特殊实现创建 B
,它不会因为在 A
?
中的实现而在编译错误中失败
这里的问题是 static_assert
是一个 编译时 特性,它在编译期间检查条件,而虚函数 call/dispatch 在 运行-时间。编译器仍然必须编译基class中的函数,这将导致断言。
"However, the aforementioned code fails because of the static assertion even though there isn't any A instanciated."
但是有一个:通过B。B是A。
"And how can I create B with a special implementation of failifint that doesn't fail in a compilation error because of its implementation in A?"
你不能,只要 A 的 failifint 是虚拟的。你可以做的是覆盖它。只需删除 virtual 关键字即可。这将隐藏 A 的 failifint。
template <typename T>
class A
{
public:
void failifint()
{
static_assert(!std::is_same<T, int>(), "T is an int!");
printf("A failifint\n");
}
};
class B : public A <int>
{
public:
void failifint()
{
printf("B\n");
}
};
如果在 main 中有以下代码,a.failifint 将给出编译时错误。
B b;
A<int> a;
b.failifint(); // B
a.failifint(); //compile error
但是,如果您必须通过虚拟方法扩展 A 的 failifint 功能,您也可以这样做
// Abstract base
template <typename T>
class A
{
public:
virtual void failifint() = 0;
};
// Can be of type int
class B : public A <int>
{
public:
void failifint()
{
printf("B\n");
}
};
// Anything deriving from C cannot be int
class C : public A <typename T>
{
public:
virtual void failifint()
{
static_assert(!std::is_same<T, int>(), "T is an int!");
printf("C failifint\n");
}
};
这将允许某些 A 对 int 抛出异常,而某些则不允许。如果它们直接派生自 A,那么你就很好。如果它们从 C 派生,则它们不能是 int 类型。
您的尝试确实有问题:
class A
{
virtual void print() { cout << "A" << endl; }
virtual ~A() { print(); }
}
class B : A
{
virtual void print() { cout << "B" << endl; }
}
...
B b;
将在析构时打印 A,而不是 B。因此当您实例化 B
时,会实例化一个 A
。
我有一些类似于下面的代码:
#include <type_traits>
template <typename T>
class A
{
virtual void failifint()
{
static_assert(!std::is_same<T, int>(), "T is an int!");
}
};
class B : public A <int>
{
virtual void failifint()
{
// Don't fail
}
};
int main()
{
B b ;
}
我希望任何包含 A<T>
对象的代码只要 T
不是 int
就可以编译,而包含 B
的代码编译,因为 failifint()
被覆盖为 int 可编译版本。但是,上述代码由于静态断言而失败,即使没有任何 A<int>
实例化。
为什么会这样?以及如何使用 failifint
的特殊实现创建 B
,它不会因为在 A
?
这里的问题是 static_assert
是一个 编译时 特性,它在编译期间检查条件,而虚函数 call/dispatch 在 运行-时间。编译器仍然必须编译基class中的函数,这将导致断言。
"However, the aforementioned code fails because of the static assertion even though there isn't any A instanciated."
但是有一个:通过B。B是A。
"And how can I create B with a special implementation of failifint that doesn't fail in a compilation error because of its implementation in A?"
你不能,只要 A 的 failifint 是虚拟的。你可以做的是覆盖它。只需删除 virtual 关键字即可。这将隐藏 A 的 failifint。
template <typename T>
class A
{
public:
void failifint()
{
static_assert(!std::is_same<T, int>(), "T is an int!");
printf("A failifint\n");
}
};
class B : public A <int>
{
public:
void failifint()
{
printf("B\n");
}
};
如果在 main 中有以下代码,a.failifint 将给出编译时错误。
B b;
A<int> a;
b.failifint(); // B
a.failifint(); //compile error
但是,如果您必须通过虚拟方法扩展 A 的 failifint 功能,您也可以这样做
// Abstract base
template <typename T>
class A
{
public:
virtual void failifint() = 0;
};
// Can be of type int
class B : public A <int>
{
public:
void failifint()
{
printf("B\n");
}
};
// Anything deriving from C cannot be int
class C : public A <typename T>
{
public:
virtual void failifint()
{
static_assert(!std::is_same<T, int>(), "T is an int!");
printf("C failifint\n");
}
};
这将允许某些 A 对 int 抛出异常,而某些则不允许。如果它们直接派生自 A,那么你就很好。如果它们从 C 派生,则它们不能是 int 类型。
您的尝试确实有问题:
class A
{
virtual void print() { cout << "A" << endl; }
virtual ~A() { print(); }
}
class B : A
{
virtual void print() { cout << "B" << endl; }
}
...
B b;
将在析构时打印 A,而不是 B。因此当您实例化 B
时,会实例化一个 A
。