virtual
требуется реализация. Объявление деструктора по-прежнему требует определения его (в отличие от обычной функции):
struct X
{
virtual ~X() = 0;
};
struct Y : X
{
~Y() {}
};
int main()
{
Y y;
}
//X::~X(){} //uncomment this line for successful definition
Это происходит потому, что деструкторы базового класса вызывается, когда объект уничтожается неявно, поэтому требуется определение.
virtual
методы должны быть реализованы или определены как чистые. Это похоже на методы не virtual
без определения, с добавлением аргументов, которые генерирует чистая декларация dummy vtable, и вы можете получить ошибку компоновщика без использования функции:
struct X
{
virtual void foo();
};
struct Y : X
{
void foo() {}
};
int main()
{
Y y; //linker error although there was no call to X::foo
}
Чтобы это сработало, объявите X::foo()
чистым:
struct X
{
virtual void foo() = 0;
};
virtual
Некоторые члены должны быть определены, даже если они явно не используются:
struct A
{
~A();
};
Следующие ошибки приведут к ошибке:
A a; //destructor undefined
Реализация может быть встроенной в самом определении класса:
struct A
{
~A() {}
};
или снаружи:
A::~A() {}
Если реализация вне определения класса, но в заголовке, методы должны быть отмечены как inline
, чтобы предотвратить множественное определение.
Все используемые методы-члены должны быть определены, если они используются.
struct A
{
void foo();
};
void foo() {}
int main()
{
A a;
a.foo();
}
Определение должно быть
void A::foo() {}
static
. Члены данных должны быть определены вне класса в единственная единица перевода: struct X
{
static int x;
};
int main()
{
int x = X::x;
}
//int X::x; //uncomment this line to define X::x
Инициализатор может быть предоставлен для элемента данных static
const
типа интеграла или перечисления в определении класса; однако odr-использование этого элемента по-прежнему потребует определения области пространства имен, как описано выше. C ++ 11 позволяет инициализировать внутри класса для всех членов static const
данных.
Насколько я понимаю, поскольку ProcessBuilder не имеет представления о том, как параметры должны передаваться команде, вам нужно передать параметры отдельно в ProcessBuilder;
ArrayList<String> test = new ArrayList<String>();
test.add("\"C:\\Program Files\\USBDeview\\USBDeview.exe\"");
test.add("/enable");
test.add("\"My USB Device\"");
Сначала вам нужно разделить аргументы самостоятельно - ProcessBuilder
не делает этого для вас - и, во-вторых, вам не нужно класть экранированные кавычки вокруг значений аргументов.
ArrayList<String> test = new ArrayList<String>();
test.add("C:\\Program Files\\USBDeview\\USBDeview.exe");
test.add("/enable");
test.add("My USB Device");
Кавычки необходимы в командной строке, чтобы сообщить парсеру cmd, как разбить слова на аргументы, но ProcessBuilder
им не нужны, потому что ему уже даны аргументы предварительного разделения.
Joachim прав, но его ответ недостаточен, когда ваш процесс ожидает унифицированных аргументов, как показано ниже:
myProcess.exe /myParameter="my value"
Как видно stefan, ProcessBuilder увидит пробелы в вашем аргументе и обернет его в кавычки, например это:
myProcess.exe "/myParameter="my value""
Разрыв значений параметров, так как рекомендует Joachim, приведет к пробелу между /myparameter=
и "my value"
, который не будет работать для этого типа параметра:
myProcess.exe /myParameter= "my value"
Согласно Sun, в их бесконечной мудрости это не ошибка, а двойные кавычки могут быть экранированы для достижения желаемого поведения.
] Чтобы окончательно ответить на вопрос Стефана, это альтернатива, которая ДОЛЖНА работать, если процесс, который вы вызываете, делает все правильно:
ArrayList<String> test = new ArrayList<String>();
test.add("\"C:\\Program Files\\USBDeview\\USBDeview.exe\"");
test.add("/enable \\\"My USB Device\\\"");
Это должно дать вам команду "C:\Program Files\USBDeview\USBDeview.exe" "/enable \"My USB Device\""
, которая может выполнять обмануть; YMMV.