C++, WinRT e classi parziali

C++, WinRT e classi parziali

Le classi parziali sono finalmente disponibili per C++. Una specie di. Non fa parte del nuovo standard C++11, fa parte del linguaggio C++/CX sviluppato da Microsoft per il targeting di WinRT su Windows 8.

Classi parziali significano che puoi definire una classe distribuita su più file. Perché è fantastico? Perché consente agli sviluppatori e agli strumenti di generazione automatica del codice (come i progettisti) di modificare parti della stessa classe senza interferire l'una con l'altra. WinRT consente agli sviluppatori C++ di scrivere l'interfaccia utente in XAML. Ciò non sarebbe stato possibile senza il supporto delle classi parziali.

Classi parziali:

  • sono disponibili solo per le classi ref; le classi native non sono supportate
  • vengono introdotti con il parziale parola chiave in tutte le definizioni tranne una

Ecco un esempio:

// 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;}

Cosa succede quando aggiungi una nuova pagina a un'applicazione in stile Metro C++? La procedura guidata genera tre file:un file XAML e un file di intestazione e cpp come codice sottostante. Diciamo che la pagina si chiama MainPage. In questo caso i tre file sono MainPage.xaml (il codice seguente è un esempio fittizio), MainPage.xaml.h e 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()
{
}

Puoi notare che gli oggetti firstPanel e primo pulsante non sono definiti nell'intestazione di MainPage e in secondo luogo, MainPage.xaml.h include MainPage.g.h. Allora cos'è questo? Questo è un file generato dal designer, che insieme a MainPage.g.cpp completa la definizione della classe ref MainPage. Questi file non vengono generati finché non avvii una build. Dopo averlo fatto, puoi trovarli nella cartella di output (Debug o Release per esempio). Ecco come appaiono:

#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)
{
}

L'immagine seguente illustra il raggruppamento di questi file:

MainPage.xaml è un file XAML, che può essere modificato sia dal designer che manualmente dallo sviluppatore (in pratica con il designer è ancora lo sviluppatore che modella l'interfaccia utente). Gli altri file sono file C++/CX. MainPage.xaml.h e MainPage.xaml.cpp sono i file scritti dallo sviluppatore, mentre MainPage.g.h e MainPage.g.cpp vengono modificati dal designer. Non modificare il codice in questi file, perché potresti rovinare il designer o tutte le modifiche andrebbero perse quando il file viene rigenerato.

CodiceProgetto