2016-11-10 5 views
1

У меня есть этот реф класс:Как инициализировать класс C++/cx с помощью агрегатной инициализации?

namespace N 
{  
    public ref class S sealed 
    { 
    public: 
     property Platform::String^ x; 
    }; 
} 

Как инициализировать его на месте с общим инициализатором? Я пробовал:

N::S s1 = { %Platform::String(L"text") }; 

но компилятор говорит

ошибка C2440: 'инициализации': не удается преобразовать из 'списка инициализатора' в 'N :: S'

Также:

N::S s1 { %Platform::String(L"text") }; 

и погрешность составляет:

C2664 ошибка: 'N :: S :: S (Const N :: S%)': не удается преобразовать аргумент 1 из 'Platform :: String ^' к 'сопзЬ N :: S%'

Это прекрасно работает со стандартным C++, как это:

struct T 
    { 
     wstring x; 
    }; 
T x { L"test" }; 

Я не хочу использовать конструктор здесь.

+0

Ваш класс ref является типом interop, свойство на самом деле не является полем в классе. Просто удобный синтаксический сахар для программиста на C++. Но для вызова функции (set_x) требуется инициализировать значение, несовместимое с списком инициализаторов. Вам нужен 's1.x =" test ";', компилятор автоматически создает платформу :: String и преобразует ее в вызов метода интерфейса. –

ответ

0

Я предполагаю, что вы не хотите, чтобы конструктор public на проецируемом тире WinRT - без проблем, вы можете использовать ключевое слово internal для обозначения «public внутри C++, но не подвергается через interop». Это означает, что вы можете даже использовать родные C++ типов для параметров, если вам нравится:

namespace Testing 
{ 
    public ref class MyTest sealed 
    { 
    public: 
    property String^ Foo { 
     String^ get() { return m_foo; } 
     void set(String^ value) { m_foo = value; } 
    } 

    internal: 
    // Would not compile if it was public, since wchar_t* isn't valid 
    MyTest(const wchar_t* value) { m_foo = ref new String(value); } 

    private: 
    String^ m_foo; 
    }; 
} 

MainPage::MainPage() 
{ 
    // Projected type does NOT have this constructor 
    Testing::MyTest t{ L"Hello" }; 
    OutputDebugString(t.Foo->Data()); 
    t.Foo = "\nChanged"; 
    OutputDebugString(t.Foo->Data()); 
} 

Также вам не нужно иметь переменную private для хранения строки - вы можете просто использовать авто-свойство, как и в ваш исходный код - но я предпочитаю быть явным. Это также означает, что если вам нужно было легко получить доступ к строке из вашего кода на C++, вы могли бы предоставить функцию доступа к объекту internal и не должны проходить через вызов vtable, чтобы добраться до него.

+0

Спасибо @Peter! Достаточно немного дополнительного кода в классе, но это нормально, так как он сохраняет мне одну строку на вызывающей стороне. –