C++, WinRT y clases parciales

C++, WinRT y clases parciales

Las clases parciales finalmente están disponibles para C++. Algo así como. No es parte del nuevo estándar C++11, es parte del lenguaje C++/CX desarrollado por Microsoft para apuntar a WinRT en Windows 8.

Las clases parciales significan que puede definir una clase distribuida en varios archivos. ¿Por qué es genial? Porque permite a los desarrolladores y herramientas generadoras automáticas de código (como los diseñadores) editar partes de la misma clase sin interferir entre sí. WinRT permite a los desarrolladores de C++ escribir la interfaz de usuario en XAML. Esto no podría haber sido posible sin el apoyo a las clases parciales.

Clases parciales:

  • están disponibles solo para clases de referencia; las clases nativas no son compatibles
  • se introducen con el parcial palabra clave en todas las definiciones excepto en una

Aquí hay un ejemplo:

// foo.private.h
#pragma once

partial ref class foo // <- here the partial keyword is used
{
private:
   int _id;
   Platform::String^ _name;
};
// foo.public.h
#pragma once
#include "foo.private.h"

ref class foo // <- partial keyword is not used here
{
public:
   int GetId();
   Platform::String^ GetName();
};
// foo.cpp
#include "pch.h"
#include "foo.public.h"

int foo::GetId() {return _id;}
Platform::String^ foo::GetName {return _name;}

¿Qué sucede cuando agrega una nueva página a una aplicación de estilo C++ Metro? El asistente genera tres archivos:un archivo XAML y un archivo de encabezado y cpp como el código subyacente. Digamos que la página se llama MainPage. En este caso, los tres archivos son MainPage.xaml (el código siguiente es un ejemplo ficticio), MainPage.xaml.h y MainPage.xaml.cpp.

<UserControl x:Class="DemoApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="768" d:DesignWidth="1366">

    <StackPanel Name="firstPanel">
        <Button Name="firstButon" />
    </StackPanel>
    
</UserControl>
//
// MainPage.xaml.h
// Declaration of the MainPage.xaml class.
//

#pragma once

#include "pch.h"
#include "MainPage.g.h"

namespace DemoApp
{
   public ref class MainPage
   {
      public:
         MainPage();
         ~MainPage();
   };
}
//
// MainPage.xaml.cpp
// Implementation of the MainPage.xaml class.
//

#include "pch.h"
#include "MainPage.xaml.h"

using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Data;
using namespace DemoApp;

MainPage::MainPage()
{
   InitializeComponent();
}

MainPage::~MainPage()
{
}

Puede notar que los objetos firstPanel y primer botón no están definidos en el encabezado de MainPage y, en segundo lugar, MainPage.xaml.h incluye MainPage.g.h. ¿Entonces qué es esto? Este es un archivo generado por el diseñador, que junto con MainPage.g.cpp completa la definición de la clase de referencia MainPage. Estos archivos no se generan hasta que inicia una compilación. Después de hacer eso, puede encontrarlos en la carpeta de salida (Debug o Release, por ejemplo). Así es como se ven:

#pragma once
//------------------------------------------------------------------------------
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
//------------------------------------------------------------------------------

namespace Windows {
    namespace UI {
        namespace Xaml {
            namespace Controls {
                ref class StackPanel;
                ref class Button;
            }
        }
    }
}

namespace DemoApp
{
    partial ref class MainPage : public Windows::UI::Xaml::Controls::UserControl, 
                                                     public Windows::UI::Xaml::Markup::IComponentConnector
    {
    public:
        void InitializeComponent();
        void Connect(int connectionId, Platform::Object^ pTarget);

    private:
        Windows::UI::Xaml::Controls::StackPanel^ firstPanel;
        Windows::UI::Xaml::Controls::Button^ firstButon;
    };
}
//------------------------------------------------------------------------------
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
//------------------------------------------------------------------------------
#include "pch.h"

#include "MainPage.xaml.h"


using namespace Windows::Foundation;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Markup;
using namespace MyDemoApplication1;

void MainPage::InitializeComponent()
{
    // Call LoadComponent on ms-resource://DemoApp/Files/MainPage.xaml
    Windows::UI::Xaml::Application::LoadComponent(this, ref new Windows::Foundation::Uri("ms-resource://DemoApp/Files/MainPage.xaml"));

    // Get the StackPanel named 'firstPanel'
    firstPanel = safe_cast<Windows::UI::Xaml::Controls::StackPanel^>(static_cast<IFrameworkElement^>(this)->FindName("firstPanel"));

    // Get the Button named 'firstButon'
    firstButon = safe_cast<Windows::UI::Xaml::Controls::Button^>(static_cast<IFrameworkElement^>(this)->FindName("firstButon"));

}

void MainPage::Connect(int connectionId, Platform::Object^ pTarget)
{
}

La siguiente imagen ilustra la agrupación de estos archivos:

MainPage.xaml es un archivo XAML que puede editar tanto el diseñador como manualmente por el desarrollador (básicamente, el diseñador sigue siendo el desarrollador que modela la interfaz de usuario). Los otros archivos son archivos C++/CX. MainPage.xaml.h y MainPage.xaml.cpp son los archivos que escribe el desarrollador, mientras que MainPage.g.h y MainPage.g.cpp son editados por el diseñador. No modifique el código en estos archivos, ya que podría estropear el diseñador o todos los cambios se perderían cuando se regenere el archivo.

Proyecto de código