Respostas:
Da função virtual da Wikipedia ...
Na programação orientada a objetos, em linguagens como C ++ e Object Pascal, uma função virtual ou método virtual é uma função ou método herdável e substituível para o qual é facilitado o envio dinâmico. Esse conceito é uma parte importante da parte do polimorfismo (tempo de execução) da programação orientada a objetos (OOP). Em resumo, uma função virtual define uma função de destino a ser executada, mas o destino pode não ser conhecido no momento da compilação.
Ao contrário de uma função não virtual, quando uma função virtual é substituída, a versão mais derivada é usada em todos os níveis da hierarquia de classes, em vez de apenas no nível em que foi criada. Portanto, se um método da classe base chamar um método virtual, a versão definida na classe derivada será usada em vez da versão definida na classe base.
Isso contrasta com as funções não virtuais, que ainda podem ser substituídas em uma classe derivada, mas a versão "nova" será usada apenas pela classe derivada e abaixo, mas não alterará a funcionalidade da classe base.
enquanto que..
Uma função virtual pura ou método virtual puro é uma função virtual que deve ser implementada por uma classe derivada se a classe derivada não for abstrata.
Quando existe um método virtual puro, a classe é "abstrata" e não pode ser instanciada sozinha. Em vez disso, uma classe derivada que implementa o (s) método (s) virtual puro (s) deve ser usada. Um virtual puro não é definido na classe base, portanto, uma classe derivada deve defini-la ou essa classe derivada também é abstrata e não pode ser instanciada. Somente uma classe que não possui métodos abstratos pode ser instanciada.
Um virtual fornece uma maneira de substituir a funcionalidade da classe base, e um virtual puro exige isso.
pure
palavra - chave, mas que o Bell Labs estava prestes a lançar um grande lançamento de C ++, e seu gerente não o permitiria nessa fase tardia. Adicionar palavras-chave é importante.
Eu gostaria de comentar sobre a definição de virtual da Wikipedia, conforme repetido por vários aqui. [No momento em que essa resposta foi escrita], a Wikipedia definia um método virtual como aquele que pode ser substituído em subclasses. [Felizmente, a Wikipedia foi editada desde então e agora explica isso corretamente.] Isso está incorreto: qualquer método, não apenas o virtual, pode ser substituído em subclasses. O que o virtual faz é fornecer polimorfismo, ou seja, a capacidade de selecionar em tempo de execução a substituição mais derivada de um método .
Considere o seguinte código:
#include <iostream>
using namespace std;
class Base {
public:
void NonVirtual() {
cout << "Base NonVirtual called.\n";
}
virtual void Virtual() {
cout << "Base Virtual called.\n";
}
};
class Derived : public Base {
public:
void NonVirtual() {
cout << "Derived NonVirtual called.\n";
}
void Virtual() {
cout << "Derived Virtual called.\n";
}
};
int main() {
Base* bBase = new Base();
Base* bDerived = new Derived();
bBase->NonVirtual();
bBase->Virtual();
bDerived->NonVirtual();
bDerived->Virtual();
}
Qual é o resultado deste programa?
Base NonVirtual called.
Base Virtual called.
Base NonVirtual called.
Derived Virtual called.
Derivado substitui todos os métodos do Base: não apenas o virtual, mas também o não virtual.
Vemos que, quando você tem um ponteiro de base para derivado (bDerived), chamar NonVirtual chama a implementação da classe Base. Isso é resolvido no momento da compilação: o compilador vê que bDerived é uma Base *, que NonVirtual não é virtual e, portanto, executa a resolução na classe Base.
No entanto, chamar Virtual chama a implementação da classe Derived. Por causa da palavra-chave virtual, a seleção do método acontece no tempo de execução , não no tempo de compilação. O que acontece aqui no momento da compilação é que o compilador vê que isso é uma Base * e que está chamando um método virtual; portanto, insere uma chamada na vtable em vez da classe Base. Essa tabela é instanciada no tempo de execução, portanto, a resolução do tempo de execução para a substituição mais derivada.
Espero que não tenha sido muito confuso. Em resumo, qualquer método pode ser substituído, mas apenas os métodos virtuais fornecem polimorfismo, ou seja, seleção em tempo de execução da substituição mais derivada. Na prática, no entanto, substituir um método não virtual é considerado uma prática ruim e raramente usada; muitas pessoas (incluindo quem escreveu esse artigo da Wikipedia) acham que apenas os métodos virtuais podem ser substituídos.
Derived*
com as mesmas chamadas de função para levar o ponto para casa. Caso contrário, grande resposta
A palavra-chave virtual fornece ao C ++ sua capacidade de suportar polimorfismo. Quando você tem um ponteiro para um objeto de alguma classe, como:
class Animal
{
public:
virtual int GetNumberOfLegs() = 0;
};
class Duck : public Animal
{
public:
int GetNumberOfLegs() { return 2; }
};
class Horse : public Animal
{
public:
int GetNumberOfLegs() { return 4; }
};
void SomeFunction(Animal * pAnimal)
{
cout << pAnimal->GetNumberOfLegs();
}
Neste exemplo (bobo), a função GetNumberOfLegs () retorna o número apropriado com base na classe do objeto para o qual é chamado.
Agora, considere a função 'SomeFunction'. Ele não se importa com o tipo de objeto animal que é passado a ele, desde que seja derivado de Animal. O compilador converterá automaticamente qualquer classe derivada de Animal para um Animal, pois é uma classe base.
Se fizermos isso:
Duck d;
SomeFunction(&d);
seria '2'. Se fizermos isso:
Horse h;
SomeFunction(&h);
seria '4'. Não podemos fazer isso:
Animal a;
SomeFunction(&a);
porque não será compilado devido à função virtual GetNumberOfLegs () ser pura, o que significa que deve ser implementada derivando classes (subclasses).
As funções virtuais puras são usadas principalmente para definir:
a) classes abstratas
Essas são classes base nas quais você deve derivar delas e implementar as funções virtuais puras.
b) interfaces
Essas são classes 'vazias', onde todas as funções são puramente virtuais e, portanto, você deve derivar e implementar todas as funções.
Em uma classe C ++, virtual é a palavra-chave que designa isso, um método pode ser substituído (isto é, implementado por) uma subclasse. Por exemplo:
class Shape
{
public:
Shape();
virtual ~Shape();
std::string getName() // not overridable
{
return m_name;
}
void setName( const std::string& name ) // not overridable
{
m_name = name;
}
protected:
virtual void initShape() // overridable
{
setName("Generic Shape");
}
private:
std::string m_name;
};
Nesse caso, uma subclasse pode substituir a função initShape para realizar algum trabalho especializado:
class Square : public Shape
{
public:
Square();
virtual ~Square();
protected:
virtual void initShape() // override the Shape::initShape function
{
setName("Square");
}
}
O termo virtual puro refere-se a funções virtuais que precisam ser implementadas por uma subclasse e não foram implementadas pela classe base. Você designa um método como virtual puro usando a palavra-chave virtual e adicionando a = 0 no final da declaração do método.
Portanto, se você deseja tornar o Shape :: initShape puro virtual, faça o seguinte:
class Shape
{
...
virtual void initShape() = 0; // pure virtual method
...
};
Ao adicionar um método virtual puro à sua classe, você torna a classe uma classe base abstrata que é muito útil para separar interfaces da implementação.
m_name
. O que m_
significa isso?
"Virtual" significa que o método pode ser substituído em subclasses, mas possui uma implementação diretamente chamada na classe base. "Virtual puro" significa que é um método virtual sem implementação de chamada direta. Esse método deve ser substituído pelo menos uma vez na hierarquia de herança - se uma classe tiver métodos virtuais não implementados, os objetos dessa classe não poderão ser construídos e a compilação falhará.
O @quark indica que os métodos puramente virtuais podem ter uma implementação, mas como os métodos puramente virtuais devem ser substituídos, a implementação padrão não pode ser chamada diretamente. Aqui está um exemplo de um método virtual puro com um padrão:
#include <cstdio>
class A {
public:
virtual void Hello() = 0;
};
void A::Hello() {
printf("A::Hello\n");
}
class B : public A {
public:
void Hello() {
printf("B::Hello\n");
A::Hello();
}
};
int main() {
/* Prints:
B::Hello
A::Hello
*/
B b;
b.Hello();
return 0;
}
Segundo os comentários, se a compilação falhará ou não é específico do compilador. No GCC 4.3.3, pelo menos, ele não compila:
class A {
public:
virtual void Hello() = 0;
};
int main()
{
A a;
return 0;
}
Resultado:
$ g++ -c virt.cpp
virt.cpp: In function ‘int main()’:
virt.cpp:8: error: cannot declare variable ‘a’ to be of abstract type ‘A’
virt.cpp:1: note: because the following virtual functions are pure within ‘A’:
virt.cpp:3: note: virtual void A::Hello()
Como a palavra-chave virtual funciona?
Suponha que o homem seja uma classe base, o indiano é derivado do homem.
Class Man
{
public:
virtual void do_work()
{}
}
Class Indian : public Man
{
public:
void do_work()
{}
}
Declarar do_work () como virtual significa simplesmente: qual do_work () chamar será determinado SOMENTE no tempo de execução.
Suponha que sim,
Man *man;
man = new Indian();
man->do_work(); // Indian's do work is only called.
Se virtual não for usado, o mesmo será determinado estaticamente ou vinculado estaticamente pelo compilador, dependendo de qual objeto está chamando. Portanto, se um objeto do homem chama do_work (), o do_work () do homem é chamado MESMO, embora aponte para um objeto indiano
Acredito que a resposta mais votada é enganosa - Qualquer método, virtual ou não, pode ter uma implementação substituída na classe derivada. Com referência específica ao C ++, a diferença correta é a ligação em tempo de execução (quando o virtual é usado) e o tempo de compilação (quando o virtual não é usado, mas um método é substituído e um ponteiro base é apontado para um objeto derivado) das funções associadas.
Parece haver outro comentário enganoso que diz:
"Justin, 'virtual puro' é apenas um termo (não uma palavra-chave, veja minha resposta abaixo) usado para significar" esta função não pode ser implementada pela classe base. "
ISTO ESTÁ ERRADO! Funções puramente virtuais também podem ter um corpo E PODEM SER IMPLEMENTADAS! A verdade é que a função virtual pura de uma classe abstrata pode ser chamada estaticamente! Dois autores muito bons são Bjarne Stroustrup e Stan Lippman .... porque eles escreveram a linguagem.
Uma função virtual é uma função de membro declarada em uma classe base e redefinida pela classe derivada. A função virtual é hierárquica em ordem de herança. Quando uma classe derivada não substitui uma função virtual, a função definida em sua classe base é usada.
Uma função virtual pura é aquela que não contém definição em relação à classe base. Não possui implementação na classe base. Qualquer classe derivada deve substituir essa função.
Simula, C ++ e C #, que usam a ligação estática de métodos por padrão, o programador pode especificar que métodos específicos usem a ligação dinâmica, rotulando-os como virtuais. A ligação de método dinâmico é fundamental para a programação orientada a objetos.
A programação orientada a objetos requer três conceitos fundamentais: encapsulamento, herança e ligação dinâmica de métodos.
O encapsulamento permite ocultar os detalhes de implementação de uma abstração atrás de uma interface simples.
A herança permite que uma nova abstração seja definida como uma extensão ou refinamento de alguma abstração existente, obtendo algumas ou todas as suas características automaticamente.
A ligação de método dinâmico permite que a nova abstração exiba seu novo comportamento mesmo quando usado em um contexto que espera a abstração antiga.
Os métodos virtuais PODEM ser substituídos pelas classes derivadas, mas precisam de uma implementação na classe base (aquela que será substituída)
Métodos virtuais puros não têm implementação na classe base. Eles precisam ser definidos por classes derivadas. (Portanto, tecnicamente substituído não é o termo certo, porque não há nada a substituir).
Virtual corresponde ao comportamento java padrão, quando a classe derivada substitui um método da classe base.
Os métodos puros virtuais correspondem ao comportamento dos métodos abstratos nas classes abstratas. E uma classe que contém apenas métodos e constantes virtuais puros seria o cpp-pendant para uma Interface.
Função Virtual Pura
tente este código
#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{
public:
virtual void sayHellow()=0;
};
class anotherClass:aClassWithPureVirtualFunction
{
public:
void sayHellow()
{
cout<<"hellow World";
}
};
int main()
{
//aClassWithPureVirtualFunction virtualObject;
/*
This not possible to create object of a class that contain pure virtual function
*/
anotherClass object;
object.sayHellow();
}
Na classe anotherClass, remova a função sayHellow e execute o código. você receberá um erro! Como quando uma classe contém uma função virtual pura, nenhum objeto pode ser criado a partir dessa classe e ele é herdado, então sua classe derivada deve implementar essa função.
Função virtual
tente outro código
#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{
public:
virtual void sayHellow()
{
cout<<"from base\n";
}
};
class anotherClass:public aClassWithPureVirtualFunction
{
public:
void sayHellow()
{
cout<<"from derived \n";
}
};
int main()
{
aClassWithPureVirtualFunction *baseObject=new aClassWithPureVirtualFunction;
baseObject->sayHellow();///call base one
baseObject=new anotherClass;
baseObject->sayHellow();////call the derived one!
}
Aqui, a função sayHellow é marcada como virtual na classe base. Diz o compilador que tenta pesquisar a função na classe derivada e implementa a função.Se não encontrado, execute a base one.Obrigado
"Uma função virtual ou método virtual é uma função ou método cujo comportamento pode ser substituído em uma classe herdada por uma função com a mesma assinatura" - wikipedia
Esta não é uma boa explicação para funções virtuais. Porque, mesmo que um membro não seja virtual, a herança de classes pode substituí-lo. Você pode tentar e ver você mesmo.
A diferença aparece quando uma função recebe uma classe base como parâmetro. Quando você fornece uma classe herdada como entrada, essa função usa a implementação da classe base da função substituída. No entanto, se essa função é virtual, ela usa a que é implementada na classe derivada.
As funções virtuais devem ter uma definição na classe base e também na classe derivada, mas não necessárias, por exemplo, a função ToString () ou toString () é uma Virtual, para que você possa fornecer sua própria implementação, substituindo-a nas classes definidas pelo usuário.
Funções virtuais são declaradas e definidas na classe normal.
A função virtual pura deve ser declarada terminando com "= 0" e só pode ser declarada na classe abstrata.
Uma classe abstrata que possui uma (s) função (s) virtual (ais) pura (s) não pode ter uma (s) definição (ões) dessa (s) função (s) virtual (is) pura (s), portanto, implica que a implementação deve ser fornecida nas classes que derivaram dessa classe abstrata.