以前,我确信你不能这样做,但前几天我正在玩一些代码,它似乎编译和工作.我只是想证实我不仅仅是幸运.模板类可以有一个纯虚函数 - 我想这也意味着普通的虚方法对于析构函数也是有效的吗?
template <typename WordType> class DataSource
{
public:
DataSource();
DataSource(DataSource const& other);
virtual ~DataSource();
virtual void Put(
WordType const* const data,
unsigned int const wordCount) = 0;
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试在网上查找它了,我能找到的就是你不能在正常的类中使用虚拟方法(纯或其他),例如:
class DataSource
{
public:
DataSource();
DataSource(DataSource const& other);
virtual ~DataSource();
template <typename WordType>
virtual void Put(
WordType const* const data,
unsigned int const wordCount) = 0;
}
Run Code Online (Sandbox Code Playgroud)
而这是由于管理虚拟表以引用此方法将实现的所有不同类型的可能类型的不可能性.
但是,当涉及模板类的虚拟成员函数时,它似乎是不同的,因为当模板类变量被实例化时,整个类本身通过模板参数"创建".此时,由于模板的"查找和替换"性质,虚拟方法就像任何其他类的方法一样.
无论如何,如果它丢失在那里再次说明问题:在tempate类中是否允许虚拟(纯和/或正常)虚拟函数?
添加override了C++ 11 以确保您编写的要覆盖基类虚函数的成员函数实际上(或不会编译).
但是在大型对象层次结构中,有时您可能会意外地编写一个成员函数,当您不想要它时会覆盖基类虚拟!例如:
struct A {
virtual void foo() { } // because obviously every class has foo().
};
struct B : A { ... };
class C : B {
private:
void foo() {
// was intended to be a private function local to C
// not intended to override A::foo(), but now does
}
};
Run Code Online (Sandbox Code Playgroud)
是否有一些编译器标志/扩展名至少会发出警告C::foo?为了便于阅读和正确,我只想强制所有覆盖使用override.
首先:我已阅读并且我现在知道在C++中虚拟模板成员函数(但是?)是不可能的.解决方法是将类作为模板,然后在member-function中使用template-argument.
但是在OOP的上下文中,我发现如果该类实际上是一个模板,下面的例子将不会非常"自然".请注意,代码实际上不起作用,但gcc-4.3.4报告:error: templates may not be ‘virtual’
#include <iostream>
#include <vector>
class Animal {
public:
template< class AMOUNT >
virtual void eat( AMOUNT amount ) const {
std::cout << "I eat like a generic Animal." << std::endl;
}
virtual ~Animal() {
}
};
class Wolf : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a wolf!" << std::endl;
}
virtual ~Wolf() {
}
};
class Fish : public …Run Code Online (Sandbox Code Playgroud) 可能重复:
C++静态虚拟成员?
我们可以使用虚拟静态方法(在C++中)吗?我试过编译以下代码:
#include <iostream>
using namespace std;
class A
{
public:
virtual static void f() {cout << "A's static method" << endl;}
};
class B :public A
{
public:
static void f() {cout << "B's static method" << endl;}
};
int main()
{
/* some code */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是编译器说:
member 'f' cannot be declared both virtual and static
Run Code Online (Sandbox Code Playgroud)
所以我猜答案是否定的,但为什么呢?
谢谢,罗恩
我需要使用虚拟<<运算符.但是,当我尝试写:
virtual friend ostream & operator<<(ostream& os,const Advertising& add);
Run Code Online (Sandbox Code Playgroud)
我得到编译器错误
错误1错误C2575:'operator <<':只有成员函数和基数可以是虚拟的
如何将此运算符设为虚拟?
在函数前使用虚拟词virtual的目的是什么?如果我想让子类覆盖父函数,我只需声明相同的函数,如void draw(){}.
class Parent {
public:
void say() {
std::cout << "1";
}
};
class Child : public Parent {
public:
void say()
{
std::cout << "2";
}
};
int main()
{
Child* a = new Child();
a->say();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出为2.
那么,为什么保留字virtual在标题中是必要的say()呢?
谢谢一堆.
来自C++背景,这让我感到惊讶.在C++中,将虚拟函数设为私有是一种很好的做法.来自http://www.gotw.ca/publications/mill18.htm:"准则#2:更喜欢将虚拟功能设为私有."
我还引用Eric Lippert的博客,来自Knights-knaves-protected-and-internal:
私有虚拟方法在C#中是非法的,这让我感到厌烦.如果我们拥有它,我会完全使用该功能.
据我所知,在C#中,您无法覆盖派生(但不是嵌套)类中的私有虚方法.为什么会这样?在C++中,访问说明符与是否可以覆盖函数无关.
#include <iostream>
using namespace std;
class CPolygon {
protected:
int width, height;
public:
virtual int area ()
{ return (0); }
};
class CRectangle: public CPolygon {
public:
int area () { return (width * height); }
};
Run Code Online (Sandbox Code Playgroud)
有汇编警告
Class '[C@1a9e0f7' has virtual method 'area' but non-virtual destructor
Run Code Online (Sandbox Code Playgroud)
如何理解这个警告以及如何改进代码?
[编辑]这个版本现在正确吗?(试图回答用这个概念来阐明自己)
#include <iostream>
using namespace std;
class CPolygon {
protected:
int width, height;
public:
virtual ~CPolygon(){};
virtual int area ()
{ return (0); }
};
class CRectangle: public CPolygon {
public: …Run Code Online (Sandbox Code Playgroud) class A {
public:
virtual void f() = 0;
};
class B : public A {
public:
void f() final override { };
};
int main() {
B* b = new B();
b->f();
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,编译器是否仍需要执行v表查找b->f();,或者是否可以B::f()直接调用,因为它已被标记final?
什么是外联虚拟方法以及它为什么会影响链接时间?
http://llvm.org/docs/CodingStandards.html说
如果在头文件中定义了一个类并且具有vtable(它具有虚方法或者它来自具有虚方法的类),则它必须始终在类中具有至少一个外联虚拟方法.如果没有这个,编译器会将vtable和RTTI复制到每个.o文件中,其中#include标题,膨胀.o文件大小和增加链接时间.