В java все ссылается, поэтому, когда у вас есть что-то вроде: Point pnt1 = new Point(0,0);
Java делает следующее:
[/g7]
Java не передает аргументы метода по ссылке; он передает их по значению. Я буду использовать пример из этого сайта :
public static void tricky(Point arg1, Point arg2) {
arg1.x = 100;
arg1.y = 100;
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
}
public static void main(String [] args) {
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
tricky(pnt1,pnt2);
System.out.println("X1: " + pnt1.x + " Y1:" + pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
}
Поток программы:
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
Создание двух разных объектов Point с двумя различными ссылками , [/g8]
System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
Как и ожидалось, выход будет:
X1: 0 Y1: 0
X2: 0 Y2: 0
В этой строке «pass-by-value» переходит в игру ...
tricky(pnt1,pnt2); public void tricky(Point arg1, Point arg2);
Ссылки pnt1
и pnt2
передаются по значению сложному методу, что означает, что теперь ваши ссылки pnt1
и pnt2
имеют свои copies
с именем arg1
и arg2
. Так же pnt1
и arg1
указывают на тот же объект. (То же самое для pnt2
и arg2
) [/g9]
В методе tricky
:
arg1.x = 100;
arg1.y = 100;
[/g10]
Далее в методе tricky
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
Здесь вы сначала создаете новую ссылку temp
Point, которая будет point в том же месте, что и arg1
справка. Затем вы перемещаете ссылку arg1
в точку в то же место, что и arg2
. Наконец, arg2
будет point в том же месте, что и temp
.
[/g11]
Отсюда область действия tricky
метод ушел, и вы больше не имеете доступа к ссылкам: arg1
, arg2
, temp
. Но важно отметить, что все, что вы делаете с этими ссылками, когда они «в жизни», будет постоянно влиять на объект, на который они указывают .
Итак, после выполнения метода tricky
, когда вы вернетесь к main
, у вас есть такая ситуация: [/g12]
Итак, теперь полное выполнение программы будет be:
X1: 0 Y1: 0
X2: 0 Y2: 0
X1: 100 Y1: 100
X2: 0 Y2: 0
typedef typename Tail::inUnion<U> dummy;
Однако я не уверен, что реализация inUnion верна. Если я правильно понимаю, этот класс не должен быть создан, поэтому вкладка «fail» никогда не будет автоматически терпеть неудачу. Возможно, было бы лучше указать, находится ли тип в объединении или нет с простым булевым значением.
template <typename T, typename TypeList> struct Contains;
template <typename T, typename Head, typename Tail>
struct Contains<T, UnionNode<Head, Tail> >
{
enum { result = Contains<T, Tail>::result };
};
template <typename T, typename Tail>
struct Contains<T, UnionNode<T, Tail> >
{
enum { result = true };
};
template <typename T>
struct Contains<T, void>
{
enum { result = false };
};
PS: Посмотрите на Boost :: Variant
PS2: посмотрите на typelists , особенно в книге Андрея Александреску: Modern C ++ Design
Я помещаю превосходный ответ JLBorges на аналогичный вопрос дословно из cplusplus.com, так как это наиболее краткое объяснение, которое я прочитал по этому вопросу.
] В шаблоне, который мы пишем, есть два типа имен, которые можно использовать - зависимые имена и не зависимые имена. Зависимое имя - это имя, которое зависит от параметра шаблона; неизменяемое имя имеет то же значение, независимо от параметров шаблона.
Например:
template< typename T > void foo( T& x, std::string str, int count ) { // these names are looked up during the second phase // when foo is instantiated and the type T is known x.size(); // dependant name (non-type) T::instance_count ; // dependant name (non-type) typename T::iterator i ; // dependant name (type) // during the first phase, // T::instance_count is treated as a non-type (this is the default) // the typename keyword specifies that T::iterator is to be treated as a type. // these names are looked up during the first phase std::string::size_type s ; // non-dependant name (type) std::string::npos ; // non-dependant name (non-type) str.empty() ; // non-dependant name (non-type) count ; // non-dependant name (non-type) }
То, что зависит от зависимого имени, может быть чем-то другим для каждого конкретного экземпляра шаблона. Как следствие, шаблоны C ++ подвержены «двухфазному поиску имен». Когда шаблон сначала анализируется (до того, как выполняется какое-либо создание), компилятор просматривает не зависящие имена. Когда происходит конкретное создание шаблона, параметры шаблона известны к тому времени, и компилятор ищет зависимые имена.
На первом этапе анализатор должен знать, является ли зависимое имя именем типа или имени не-типа. По умолчанию зависимым именем считается имя не-типа.
Использовать ключевое слово typename только в объявлениях шаблонов и определениях, приведенных ниже.
blockquote>
у вас есть квалифицированное имя, которое относится к типу и зависит от параметра шаблона.