typedef typename Tail::inUnion dummy;
Однако я не уверен, что реализация inUnion верна. Если я правильно понимаю, этот класс не должен быть создан, поэтому вкладка «fail» никогда не будет автоматически терпеть неудачу. Возможно, было бы лучше указать, находится ли тип в объединении или нет с простым булевым значением.
template
struct Contains; template struct Contains > { enum { result = Contains ::result }; }; template struct Contains > { enum { result = true }; }; template struct Contains { enum { result = false }; }; PS: Посмотрите на Boost :: Variant
PS2: посмотрите на typelists , особенно в книге Андрея Александреску: Modern C ++ Design
"Новое" ключевое слово не переопределяет, оно показывает новый метод, который не имеет никакого отношения к методу базового класса.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}
Это печатает ложь при использовании переопределения, это распечатало бы верный.
(Основной код, взятый от Joseph Daigle)
Так, при выполнении реального полиморфизма, НЕОБХОДИМО ВСЕГДА ПЕРЕОПРЕДЕЛЯТЬ . Единственное место, где необходимо использовать "новый", - когда метод не связан всегда с версией базового класса.
Я всегда нахожу вещи как это более понятными с изображениями:
Снова, беря joseph код daigle,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
, Если Вы тогда называете код как это:
Foo a = new Bar();
a.DoSomething();
ПРИМЕЧАНИЕ: важная вещь состоит в том, что наш объект на самом деле Bar
, но мы хранение его в переменной типа Foo
(это подобно кастингу его)
Тогда, результат будет следующим образом, в зависимости от того, использовали ли Вы virtual
/ override
или new
при объявлении классов.
Вот некоторый код для понимания различия в поведении виртуальных и невиртуальных методов:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
new
ключевое слово на самом деле создает абсолютно нового участника, который только существует на том определенном типе.
, Например
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
метод существует на обоих типах. Когда Вы будете использовать отражение и получаете членов типа Bar
, Вы на самом деле найдете 2 метода названными DoSomething()
, которые смотрят точно то же. При помощи new
Вы эффективно скрываете реализацию в базовом классе, так, чтобы, когда классы происходят от Bar
(в моем примере) вызов метода base.DoSomething()
перешел в Bar
а не Foo
.
виртуальный / переопределение говорит компилятору, что эти два метода связаны и что при некоторых обстоятельствах, когда Вы думали бы, что называете первый (виртуальный) метод, который это на самом деле корректно для вызова второго (переопределенного) метода вместо этого. Это - основа полиморфизма.
(new SubClass() as BaseClass).VirtualFoo()
будет звонить, SubClass имеет overriden VirtualFoo () метод.
новый говорит компилятору, что Вы добавляете метод к производному классу с тем же именем как метод в базовом классе, но у них нет отношений друг к другу.
(new SubClass() as BaseClass).NewBar()
назовет NewBar BaseClass () методом, тогда как:
(new SubClass()).NewBar()
назовет NewBar SubClass () методом.
Вне просто технических деталей я думаю с помощью виртуального / переопределение передает большую семантическую информацию о дизайне. Когда Вы объявляете виртуальный метод, Вы указываете, что ожидаете, что классы с реализацией могут хотеть обеспечить свои собственные, реализации не по умолчанию. Исключение этого в базовом классе, аналогично, объявляет ожидание, что метод по умолчанию должен быть достаточным для всех классов с реализацией. Точно так же можно использовать абстрактные объявления, чтобы вынудить классы с реализацией обеспечить свою собственную реализацию. Снова, я думаю, что это связывается много о том, как программист ожидает, что код будет использоваться. Если бы я писал и базовые классы и классы с реализацией и использовал новый, то я серьезно заново продумал бы решение не сделать метод виртуальным в родителе и объявить мое намерение конкретно.
Различие между ключевым словом переопределения и новым ключевым словом - то, что первый делает переопределение метода, и позже делает сокрытие метода.
Выезд следующие ссылки для получения дополнительной информации...